Skip to content

Commit

Permalink
Use rAF approach for PaddingVisualizer as well
Browse files Browse the repository at this point in the history
ResizeObserver doesn't work in the case where an element with a fixed
width has its padding changed.
  • Loading branch information
noisysocks committed Feb 23, 2024
1 parent 14929a8 commit 97956db
Showing 1 changed file with 35 additions and 23 deletions.
58 changes: 35 additions & 23 deletions packages/block-editor/src/hooks/padding.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
/**
* WordPress dependencies
*/
import { useState, useRef, useEffect } from '@wordpress/element';
import {
useState,
useRef,
useLayoutEffect,
useEffect,
} from '@wordpress/element';
import isShallowEqual from '@wordpress/is-shallow-equal';

/**
Expand All @@ -20,33 +25,40 @@ export function PaddingVisualizer( { clientId, value, forceShow } ) {
const blockElement = useBlockElement( clientId );
const [ style, setStyle ] = useState();

useEffect( () => {
const padding = value?.spacing?.padding;

useLayoutEffect( () => {
if ( ! blockElement ) {
return;
}
// It's not sufficient to read the computed padding value when value.spacing.padding
// changes as useEffect may run before the browser recomputes CSS and paints. Instead,
// we use a ResizeObserver with the box option set to 'border-box' to listen out for
// changes to the padding.
const observer = new window.ResizeObserver( () => {
setStyle( {
borderTopWidth: getComputedCSS( blockElement, 'padding-top' ),
borderRightWidth: getComputedCSS(
blockElement,
'padding-right'
),
borderBottomWidth: getComputedCSS(
blockElement,
'padding-bottom'
),
borderLeftWidth: getComputedCSS( blockElement, 'padding-left' ),
} );
} );
observer.observe( blockElement, { box: 'border-box' } );
return () => observer.disconnect();
}, [ blockElement ] );
// changes as useEffect may run before the browser recomputes CSS. We therefore combine
// useLayoutEffect and two rAF calls to ensure that we read the padding after the current
// paint but before the next paint.
window.requestAnimationFrame( () =>
window.requestAnimationFrame( () => {
setStyle( {
borderTopWidth: getComputedCSS(
blockElement,
'padding-top'
),
borderRightWidth: getComputedCSS(
blockElement,
'padding-right'
),
borderBottomWidth: getComputedCSS(
blockElement,
'padding-bottom'
),
borderLeftWidth: getComputedCSS(
blockElement,
'padding-left'
),
} );
} )
);
}, [ blockElement, padding ] );

const padding = value?.spacing?.padding;
const previousPadding = useRef( padding );
const [ isActive, setIsActive ] = useState( false );

Expand Down

0 comments on commit 97956db

Please sign in to comment.