Skip to content

Commit c92a17c

Browse files
committed
fix: Popup - Remove document listeners on unmount
- drop pointerdown/pointerup/keydown capture listeners so remounts do not keep closing menus - render Gallery slides as img elements instead of CSS background-image
1 parent 75dd776 commit c92a17c

3 files changed

Lines changed: 40 additions & 36 deletions

File tree

src/components/Gallery/Gallery.styl

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,25 @@
5454
display flex
5555
align-items center
5656
justify-content center
57-
background-size contain
58-
background-position center
59-
background-repeat no-repeat
6057
width calc(100% / 3)
58+
position relative
6159

62-
.cover &
63-
background-size cover
60+
.image
61+
max-width 100%
62+
max-height 100%
63+
width auto
64+
height auto
65+
object-fit contain
66+
opacity 0
67+
transition opacity .15s ease-out
6468

65-
& > img
66-
opacity 0
67-
position absolute
68-
pointer-events none
69+
&.imageLoaded
70+
opacity 1
71+
72+
.cover &
73+
width 100%
74+
height 100%
75+
object-fit cover
6976

7077
.brokenImage
7178
height 50%

src/components/Gallery/Gallery.tsx

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
Component,
33
createRef,
4-
CSSProperties,
54
useEffect,
65
useLayoutEffect,
76
useRef,
@@ -116,7 +115,6 @@ function Item({
116115
}) {
117116
const [loaded, setLoaded] = useState(false);
118117
const [isError, setIsError] = useState(false);
119-
const style = {} as CSSProperties;
120118
const imgRef = useRef<HTMLImageElement | null>(null);
121119

122120
useLayoutEffect(() => {
@@ -166,24 +164,24 @@ function Item({
166164
return <VideoItem src={src} size={size} isActive={isActive} />;
167165
}
168166

169-
if (loaded) style.backgroundImage = `url(${src})`;
170-
171167
return (
172-
<div className={S.item} style={style}>
173-
{!loaded &&
174-
(isError ? (
175-
<Icon type="brokenImage" className={S.brokenImage} />
176-
) : (
177-
<>
178-
<img
179-
ref={imgRef}
180-
src={src}
181-
onLoad={() => setLoaded(true)}
182-
onError={() => setIsError(true)}
183-
/>
184-
<Spinner size={size} />
185-
</>
186-
))}
168+
<div className={S.item}>
169+
{isError ? (
170+
<Icon type="brokenImage" className={S.brokenImage} />
171+
) : (
172+
<>
173+
<img
174+
ref={imgRef}
175+
src={src}
176+
alt=""
177+
className={cn(S.image, loaded && S.imageLoaded)}
178+
draggable={false}
179+
onLoad={() => setLoaded(true)}
180+
onError={() => setIsError(true)}
181+
/>
182+
{!loaded && <Spinner size={size} />}
183+
</>
184+
)}
187185
</div>
188186
);
189187
}

src/components/Popup/Popup.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ export class Popup extends Component<T.Props, T.State> {
166166
vv.removeEventListener('scroll', this.onBoundaryGeometryChange);
167167
}
168168

169+
// These are registered in componentDidMount; omitting removal left orphaned
170+
// capture listeners that kept calling close/onClose after portal remounts.
171+
document.removeEventListener('pointerdown', this.onDocPointerDown, true);
172+
document.removeEventListener('pointerup', this.onDocPointerUp, true);
173+
document.removeEventListener('keydown', this.onDocKeyDown, true);
169174
document.removeEventListener('keyup', this.onDocKeyUp);
170175

171176
if (this.scrollParent) {
@@ -289,12 +294,7 @@ export class Popup extends Component<T.Props, T.State> {
289294
const availWidth = H.edgesWidth(bounds);
290295
const fitWidth =
291296
availWidth >= BOUNDARY_FIT_EPSILON ? Math.floor(availWidth) : null;
292-
const measured = this.measureBoundaryRect(
293-
el,
294-
wrapper,
295-
fitWidth,
296-
bounds
297-
);
297+
const measured = this.measureBoundaryRect(el, wrapper, fitWidth, bounds);
298298

299299
this.setBoundaryFit(
300300
H.fitRectToBoundary(measured.rect, bounds, measured.maxWidth)
@@ -455,8 +455,7 @@ export class Popup extends Component<T.Props, T.State> {
455455
this.focused = true;
456456
this.props.triggerProps?.onFocus?.(e);
457457

458-
if (!this.pointerPressed && !this.state.isOpen)
459-
this.open();
458+
if (!this.pointerPressed && !this.state.isOpen) this.open();
460459
};
461460

462461
onBlur = e => {

0 commit comments

Comments
 (0)