Skip to content

Commit

Permalink
Add observer to provide a clear message for the current color selection.
Browse files Browse the repository at this point in the history
  • Loading branch information
juanfra authored and Mamaduka committed Dec 26, 2024
1 parent 4ad26e1 commit e86c778
Showing 1 changed file with 71 additions and 21 deletions.
92 changes: 71 additions & 21 deletions packages/block-editor/src/hooks/contrast-checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,90 @@ function getComputedStyle( node ) {
return node.ownerDocument.defaultView.getComputedStyle( node );
}

function detectColors( blockEl ) {
if ( ! blockEl ) {
return;
}

const firstLinkElement = blockEl.querySelector( 'a' );
const linkColor =
firstLinkElement && !! firstLinkElement.innerText
? getComputedStyle( firstLinkElement ).color
: null;

const textColor = getComputedStyle( blockEl ).color;

let backgroundColorNode = blockEl;
let backgroundColor =
getComputedStyle( backgroundColorNode ).backgroundColor;
while (
backgroundColor === 'rgba(0, 0, 0, 0)' &&
backgroundColorNode.parentNode &&
backgroundColorNode.parentNode.nodeType ===
backgroundColorNode.parentNode.ELEMENT_NODE
) {
backgroundColorNode = backgroundColorNode.parentNode;
backgroundColor =
getComputedStyle( backgroundColorNode ).backgroundColor;
}

return {
textColor,
backgroundColor,
linkColor,
};
}

function createStyleObserver( node, callback ) {
// Watch for changes to style-related attributes
const observer = new MutationObserver( ( mutations ) => {
const hasStyleChanges = mutations.some(
( mutation ) => mutation.attributeName === 'style'
);

if ( hasStyleChanges ) {
const computedStyle =
node.ownerDocument.defaultView.getComputedStyle( node );
callback( computedStyle );
}
} );

// Observe style-related changes
observer.observe( node, {
attributeFilter: [ 'style' ],
} );

return observer;
}

export default function BlockColorContrastChecker( { clientId } ) {
const [ detectedBackgroundColor, setDetectedBackgroundColor ] = useState();
const [ detectedColor, setDetectedColor ] = useState();
const [ detectedLinkColor, setDetectedLinkColor ] = useState();
const blockEl = useBlockElement( clientId );

// There are so many things that can change the color of a block
// So we perform this check on every render.
useEffect( () => {
if ( ! blockEl ) {
return;
}
setDetectedColor( getComputedStyle( blockEl ).color );

const firstLinkElement = blockEl.querySelector( 'a' );
if ( firstLinkElement && !! firstLinkElement.innerText ) {
setDetectedLinkColor( getComputedStyle( firstLinkElement ).color );
}

let backgroundColorNode = blockEl;
let backgroundColor =
getComputedStyle( backgroundColorNode ).backgroundColor;
while (
backgroundColor === 'rgba(0, 0, 0, 0)' &&
backgroundColorNode.parentNode &&
backgroundColorNode.parentNode.nodeType ===
backgroundColorNode.parentNode.ELEMENT_NODE
) {
backgroundColorNode = backgroundColorNode.parentNode;
backgroundColor =
getComputedStyle( backgroundColorNode ).backgroundColor;
let colors = detectColors( blockEl );
setDetectedColor( colors.textColor );
setDetectedBackgroundColor( colors.backgroundColor );
if ( colors.linkColor ) {
setDetectedLinkColor( colors.linkColor );
}

setDetectedBackgroundColor( backgroundColor );
const observer = createStyleObserver( blockEl, () => {
colors = detectColors( blockEl );
setDetectedColor( colors.textColor );
setDetectedBackgroundColor( colors.backgroundColor );
if ( colors.linkColor ) {
setDetectedLinkColor( colors.linkColor );
}
} );
// Cleanup
return () => observer.disconnect();
}, [ blockEl ] );

return (
Expand Down

0 comments on commit e86c778

Please sign in to comment.