Skip to content

Commit fea614a

Browse files
authored
Fix legacy widget height overflow (#33191)
1 parent bded4ae commit fea614a

File tree

1 file changed

+55
-27
lines changed
  • packages/widgets/src/blocks/legacy-widget/edit

1 file changed

+55
-27
lines changed

packages/widgets/src/blocks/legacy-widget/edit/preview.js

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,54 @@ import { Placeholder, Spinner, Disabled } from '@wordpress/components';
1313
import { __ } from '@wordpress/i18n';
1414

1515
export default function Preview( { idBase, instance, isVisible } ) {
16-
const [ iframeHeight, setIframeHeight ] = useState();
16+
const [ isLoaded, setIsLoaded ] = useState( false );
1717

1818
// Resize the iframe on either the load event, or when the iframe becomes visible.
19-
const ref = useRefEffect( ( iframe ) => {
20-
function onChange() {
21-
const boundingRect = iframe?.contentDocument?.body?.getBoundingClientRect();
22-
if ( boundingRect ) {
23-
// Include `top` in the height calculation to avoid the bottom
24-
// of widget previews being cut-off. Most widgets have a
25-
// heading at the top that has top margin, and the `height`
26-
// alone doesn't take that margin into account.
27-
setIframeHeight( boundingRect.top + boundingRect.height );
28-
}
29-
}
19+
const ref = useRefEffect(
20+
( iframe ) => {
21+
// Only set height if the iframe is loaded,
22+
// or it will grow to an unexpected large height in Safari if it's hidden initially.
23+
if ( isLoaded ) {
24+
// If the preview frame has another origin then this won't work.
25+
// One possible solution is to add custom script to call `postMessage` in the preview frame.
26+
// Or, better yet, we migrate away from iframe.
27+
function setHeight() {
28+
// Pick the maximum of these two values to account for margin collapsing.
29+
const height = Math.max(
30+
iframe.contentDocument.documentElement.offsetHeight,
31+
iframe.contentDocument.body.offsetHeight
32+
);
33+
iframe.style.height = `${ height }px`;
34+
}
3035

31-
const { IntersectionObserver } = iframe.ownerDocument.defaultView;
36+
const {
37+
IntersectionObserver,
38+
} = iframe.ownerDocument.defaultView;
3239

33-
// Observe for intersections that might cause a change in the height of
34-
// the iframe, e.g. a Widget Area becoming expanded.
35-
const intersectionObserver = new IntersectionObserver( onChange, {
36-
threshold: 1,
37-
} );
38-
intersectionObserver.observe( iframe );
40+
// Observe for intersections that might cause a change in the height of
41+
// the iframe, e.g. a Widget Area becoming expanded.
42+
const intersectionObserver = new IntersectionObserver(
43+
( [ entry ] ) => {
44+
if ( entry.isIntersecting ) {
45+
setHeight();
46+
}
47+
},
48+
{
49+
threshold: 1,
50+
}
51+
);
52+
intersectionObserver.observe( iframe );
3953

40-
iframe.addEventListener( 'load', onChange );
54+
iframe.addEventListener( 'load', setHeight );
4155

42-
return () => {
43-
iframe.removeEventListener( 'load', onChange );
44-
};
45-
}, [] );
56+
return () => {
57+
intersectionObserver.disconnect();
58+
iframe.removeEventListener( 'load', setHeight );
59+
};
60+
}
61+
},
62+
[ isLoaded ]
63+
);
4664

4765
return (
4866
<>
@@ -53,7 +71,7 @@ export default function Preview( { idBase, instance, isVisible } ) {
5371
move the iframe off-screen instead of hiding it because web browsers
5472
will not trigger onLoad if the iframe is hidden.
5573
*/ }
56-
{ isVisible && iframeHeight === null && (
74+
{ isVisible && ! isLoaded && (
5775
<Placeholder>
5876
<Spinner />
5977
</Placeholder>
@@ -62,7 +80,7 @@ export default function Preview( { idBase, instance, isVisible } ) {
6280
className={ classnames(
6381
'wp-block-legacy-widget__edit-preview',
6482
{
65-
'is-offscreen': ! isVisible || iframeHeight === null,
83+
'is-offscreen': ! isVisible || ! isLoaded,
6684
}
6785
) }
6886
>
@@ -84,7 +102,17 @@ export default function Preview( { idBase, instance, isVisible } ) {
84102
instance,
85103
},
86104
} ) }
87-
height={ iframeHeight || 100 }
105+
onLoad={ ( event ) => {
106+
// To hide the scrollbars of the preview frame for some edge cases,
107+
// such as negative margins in the Gallery Legacy Widget.
108+
// It can't be scrolled anyway.
109+
// TODO: Ideally, this should be fixed in core.
110+
event.target.contentDocument.body.style.overflow =
111+
'hidden';
112+
113+
setIsLoaded( true );
114+
} }
115+
height={ 100 }
88116
/>
89117
</Disabled>
90118
</div>

0 commit comments

Comments
 (0)