From e8569b3bb36b4b89f05dc689276c120d6652b156 Mon Sep 17 00:00:00 2001 From: Juan Aldasoro Date: Fri, 15 Nov 2024 15:27:40 +0100 Subject: [PATCH 1/3] Add observer to provide a clear message for the current color selection. --- .../src/hooks/contrast-checker.js | 92 ++++++++++++++----- 1 file changed, 71 insertions(+), 21 deletions(-) diff --git a/packages/block-editor/src/hooks/contrast-checker.js b/packages/block-editor/src/hooks/contrast-checker.js index 368e2e7526485..1ed99511dadbf 100644 --- a/packages/block-editor/src/hooks/contrast-checker.js +++ b/packages/block-editor/src/hooks/contrast-checker.js @@ -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 ( From 2ec285b0a85bda8d620884fad7c56a9c73a42e21 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Thu, 26 Dec 2024 11:43:38 +0400 Subject: [PATCH 2/3] Fix ESLint error --- packages/block-editor/src/hooks/contrast-checker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/contrast-checker.js b/packages/block-editor/src/hooks/contrast-checker.js index 1ed99511dadbf..5468b0a5bb1ee 100644 --- a/packages/block-editor/src/hooks/contrast-checker.js +++ b/packages/block-editor/src/hooks/contrast-checker.js @@ -49,7 +49,7 @@ function detectColors( blockEl ) { function createStyleObserver( node, callback ) { // Watch for changes to style-related attributes - const observer = new MutationObserver( ( mutations ) => { + const observer = new window.MutationObserver( ( mutations ) => { const hasStyleChanges = mutations.some( ( mutation ) => mutation.attributeName === 'style' ); From d3ed0875ad3cfa45abf8192bb7515f4b264fda29 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Thu, 26 Dec 2024 12:59:02 +0400 Subject: [PATCH 3/3] Minor stylistic changes --- .../src/hooks/contrast-checker.js | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/packages/block-editor/src/hooks/contrast-checker.js b/packages/block-editor/src/hooks/contrast-checker.js index 5468b0a5bb1ee..01ec394408fb9 100644 --- a/packages/block-editor/src/hooks/contrast-checker.js +++ b/packages/block-editor/src/hooks/contrast-checker.js @@ -13,7 +13,7 @@ function getComputedStyle( node ) { return node.ownerDocument.defaultView.getComputedStyle( node ); } -function detectColors( blockEl ) { +function getBlockColors( blockEl ) { if ( ! blockEl ) { return; } @@ -48,22 +48,21 @@ function detectColors( blockEl ) { } function createStyleObserver( node, callback ) { - // Watch for changes to style-related attributes + // Watch for changes to style-related attributes. const observer = new window.MutationObserver( ( mutations ) => { const hasStyleChanges = mutations.some( - ( mutation ) => mutation.attributeName === 'style' + ( mutation ) => + mutation.attributeName === 'style' || + mutation.attributeName === 'class' ); if ( hasStyleChanges ) { - const computedStyle = - node.ownerDocument.defaultView.getComputedStyle( node ); - callback( computedStyle ); + callback(); } } ); - // Observe style-related changes observer.observe( node, { - attributeFilter: [ 'style' ], + attributeFilter: [ 'style', 'class' ], } ); return observer; @@ -80,22 +79,20 @@ export default function BlockColorContrastChecker( { clientId } ) { return; } - let colors = detectColors( blockEl ); - setDetectedColor( colors.textColor ); - setDetectedBackgroundColor( colors.backgroundColor ); - if ( colors.linkColor ) { - setDetectedLinkColor( colors.linkColor ); - } - - const observer = createStyleObserver( blockEl, () => { - colors = detectColors( blockEl ); + function updateContrastChecker() { + const colors = getBlockColors( blockEl ); setDetectedColor( colors.textColor ); setDetectedBackgroundColor( colors.backgroundColor ); if ( colors.linkColor ) { setDetectedLinkColor( colors.linkColor ); } - } ); - // Cleanup + } + + // Check colors on mount. + updateContrastChecker(); + + const observer = createStyleObserver( blockEl, updateContrastChecker ); + return () => observer.disconnect(); }, [ blockEl ] );