Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/lightbox-double-click-point.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[fix] Lightbox: a double-click now zooms 2× about the clicked point instead of about the centre, and the next goes back; the keyboard keeps its 2× zoom about the centre.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/lightbox-every-pointer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[feat] Lightbox: a ctrl-wheel or a trackpad pinch now zooms a photo, and a trackpad's scroll pans a zoomed photo.

@vjeux
9 changes: 9 additions & 0 deletions .changeset/lightbox-touch-zoom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@astryxdesign/core': patch
---

[feat] Lightbox's zoom now works under a finger the way the iOS Photos viewer does, on a phone, a tablet or a touchscreen laptop. Pinch the photo to zoom around your fingers, and move them to pan while you zoom. Past the zoom limits the photo gives way, then springs back when you let go, at the speed your fingers had. Double-tap zooms until the photo fills the screen, at least 2×, and keeps the tapped point under your finger; double-tap again to go back. On a phone or a tablet, a zoomed photo pans with momentum, stretches past its edges and settles back. The keyboard keeps the zoom it had, 2× about the centre, and keyboard panning now stops at the photo's edges instead of carrying it out of view. Every zoom, a double tap's and a key's included, settles on the same spring.

The photo's stage fills the viewer. A pinch on the photo no longer zooms the page, and a pinch on the controls or caption still does. With `hasZoom` on, a tap on the dark area beside the photo closes the viewer after the double-tap wait instead of at once; a click still closes it at once. The zoom animations run on the compositor, so they stay smooth while the page is busy. With `hasZoom` off, nothing changes. With `hasZoom`, Close, Previous, Next and the counter sit on a dark translucent backing, so they stay readable over a zoomed photo.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/uikit-zoom-media.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] Internal: the UIKit constants table gains UIScrollView zooming for a photo viewer, measured on iOS 26.2. It holds the give past the zoom limits and Photos' aspect-fill double tap and maximum zoom. The zoom stage geometry that Lightbox's touch zoom is built on comes with it. Neither is exported from the package entry point, and Lightbox's touch zoom reads them.

@vjeux
42 changes: 42 additions & 0 deletions apps/storybook/stories/Lightbox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,48 @@ export const WithZoom: Story = {
},
};

/** Zoom on a photo with a caption, which sits under the fitted photo. */
export const ZoomWithCaption: Story = {
render: () => {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => setIsOpen(true)}>Open zoom with caption</button>
<Lightbox
isOpen={isOpen}
onOpenChange={setIsOpen}
media={{
src: SAMPLE_IMAGE,
alt: 'Forest path',
caption: 'A winding path through the forest',
}}
hasZoom
/>
</>
);
},
};

export const GalleryWithZoom: Story = {
render: () => {
const [isOpen, setIsOpen] = useState(false);
const [index, setIndex] = useState(0);
return (
<>
<button onClick={() => setIsOpen(true)}>Open gallery with zoom</button>
<Lightbox
isOpen={isOpen}
onOpenChange={setIsOpen}
media={GALLERY_MEDIA}
index={index}
onIndexChange={setIndex}
hasZoom
/>
</>
);
},
};

export const WithCaption: Story = {
render: () => {
const [isOpen, setIsOpen] = useState(false);
Expand Down
74 changes: 41 additions & 33 deletions docs/specs/components/Lightbox/Lightbox.spec.md

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions packages/core/src/Lightbox/Lightbox.doc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export const docs = {
name: 'hasZoom',
type: 'boolean',
description:
'Enable zoom on double-click, or Enter/Space/+/- via keyboard (images only). When zoomed, drag or use arrow keys to pan.',
'Enable zoom (images only): pinch (or ctrl-wheel), or double-tap or double-click to zoom in at that point and back; Enter/Space/+/- zoom 2× about the centre and back. When zoomed, drag or scroll a trackpad to pan, or use arrow keys; on a phone or a tablet, the pan has momentum.',
default: 'false',
},
{
Expand Down Expand Up @@ -211,7 +211,8 @@ export const docsZh = {
{
name: 'hasZoom',
type: 'boolean',
description: '启用双击缩放(仅图片)。缩放后可拖动平移。',
description:
'启用缩放(仅图片):双指捏合(或按住 Ctrl 滚动滚轮),或双点按、双击在该处放大并还原;Enter/Space/+/- 键以中心放大 2 倍并还原。缩放后可拖动或在触控板上滚动平移,或用方向键平移;在手机或平板上,平移带惯性。',
default: 'false',
},
{
Expand Down Expand Up @@ -296,7 +297,7 @@ export const docsDense = {
index: 'Current index in gallery mode.',
onIndexChange: 'Callback when gallery index changes.',
hasZoom:
'Enable zoom (double-click, Enter/Space, or +/-) and pan (drag or arrow keys) for images.',
'Enable zoom (pinch or ctrl-wheel, double-tap or double-click, Enter/Space, or +/-) and pan (drag, trackpad scroll, or arrow keys) for images.',
xstyle: 'StyleX styles for layout customization.',
},
};
Loading
Loading