Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ export interface UncontrolledProps {
// Default: 'Expand image'
a11yNameButtonZoom?: string

// Allow swipe gesture to unzoom.
// Default: true
canSwipeToUnzoom?: boolean

// Your image (required).
children: ReactNode

Expand All @@ -88,6 +92,10 @@ export interface UncontrolledProps {
// Default: IEnlarge
IconZoom?: ElementType

// Swipe gesture threshold after which to unzoom.
// Default: 10
swipeToUnzoomThreshold?: number

// Specify what type of element should be used for
// internal component usage. This is useful if the
// image is inside a <p> or <button>, for example.
Expand Down
20 changes: 10 additions & 10 deletions source/Controlled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ const defaultBodyAttrs: BodyAttrs = {
export interface ControlledProps {
a11yNameButtonUnzoom?: string
a11yNameButtonZoom?: string
canSwipeToUnzoom?: boolean
children: React.ReactNode
classDialog?: string
IconUnzoom?: React.ElementType
IconZoom?: React.ElementType
isZoomed: boolean
onZoomChange?: (value: boolean) => void
canSwipeToUnzoom?: boolean
swipeToUnzoomThreshold?: number
wrapElement?: 'div' | 'span'
ZoomContent?: (data: {
Expand All @@ -82,9 +82,9 @@ interface ControlledDefaultProps {
a11yNameButtonUnzoom: string
a11yNameButtonZoom: string
canSwipeToUnzoom: boolean
swipeToUnzoomThreshold: number
IconUnzoom: React.ElementType
IconZoom: React.ElementType
swipeToUnzoomThreshold: number
wrapElement: 'div' | 'span'
zoomMargin: number
}
Expand All @@ -103,9 +103,9 @@ class ControlledBase extends React.Component<ControlledPropsWithDefaults, Contro
static defaultProps: ControlledDefaultProps = {
a11yNameButtonUnzoom: 'Minimize image',
a11yNameButtonZoom: 'Expand image',
canSwipeToUnzoom: true,
IconUnzoom: ICompress,
IconZoom: IEnlarge,
canSwipeToUnzoom: true,
swipeToUnzoomThreshold: 10,
wrapElement: 'div',
zoomMargin: 0,
Expand Down Expand Up @@ -549,21 +549,21 @@ class ControlledBase extends React.Component<ControlledPropsWithDefaults, Contro
* and unzoom if we detect a swipe
*/
handleTouchMove = (e: TouchEvent) => {
if (!this.props.canSwipeToUnzoom) {
return
}

const browserScale = window.visualViewport?.scale ?? 1

if (!this.isScaling && browserScale <= 1 && this.touchYStart != null && e.changedTouches[0]) {
if (
this.props.canSwipeToUnzoom &&
!this.isScaling &&
browserScale <= 1 && this.touchYStart != null &&
e.changedTouches[0]
) {
this.touchYEnd = e.changedTouches[0].screenY

const max = Math.max(this.touchYStart, this.touchYEnd)
const min = Math.min(this.touchYStart, this.touchYEnd)
const delta = Math.abs(max - min)
const { swipeToUnzoomThreshold } = this.props

if (delta > swipeToUnzoomThreshold) {
if (delta > this.props.swipeToUnzoomThreshold) {
this.touchYStart = undefined
this.touchYEnd = undefined
this.handleUnzoom()
Expand Down
52 changes: 52 additions & 0 deletions stories/Img.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,58 @@ export const InlineImage = (props) => (
</main>
)

// =============================================================================

export const SwipeToUnzoomDisabled = (props) => (
<main aria-label="Story">
<h1>Swipe to Unzoom Disabled</h1>
<p>
This example demonstrates preventing swipe gestures from
unzooming when an image is zoomed. This is best tested on
a touchscreen device!
</p>
<div>
<Zoom {...props} canSwipeToUnzoom={false}>
<img
alt={imgThatWanakaTree.alt}
src={imgThatWanakaTree.src}
decoding="async"
height="320"
loading="lazy"
/>
</Zoom>
</div>
</main>
)

export const SwipeToUnzoomThreshold = (props) => (
<main aria-label="Story">
<h1>Swipe to Unzoom Threshold</h1>
<p>
This example demonstrates increasing the threshold
required for a swipe gesture on a touchscreen device to
unzoom when an image is zoomed. This is best tested on
a touchscreen device!
</p>
<p>
The default is <code>10</code> (px), but this example
is set to <code>200</code> (px); that&apos;s how far
you&apos;ll have to move your finger across the screen.
</p>
<div>
<Zoom {...props} swipeToUnzoomThreshold={200}>
<img
alt={imgThatWanakaTree.alt}
src={imgThatWanakaTree.src}
decoding="async"
height="320"
loading="lazy"
/>
</Zoom>
</div>
</main>
)

// =============================================================================
// INTERACTIONS

Expand Down