Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navigation block: avoid selector + style recalc on mount #60572

Merged
merged 1 commit into from
Apr 8, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 129 additions & 98 deletions packages/block-library/src/navigation/edit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,116 @@ import AccessibleDescription from './accessible-description';
import AccessibleMenuDescription from './accessible-menu-description';
import { unlock } from '../../lock-unlock';

function ColorTools( {
textColor,
setTextColor,
backgroundColor,
setBackgroundColor,
overlayTextColor,
setOverlayTextColor,
overlayBackgroundColor,
setOverlayBackgroundColor,
clientId,
navRef,
} ) {
const [ detectedBackgroundColor, setDetectedBackgroundColor ] = useState();
const [ detectedColor, setDetectedColor ] = useState();
const [
detectedOverlayBackgroundColor,
setDetectedOverlayBackgroundColor,
] = useState();
const [ detectedOverlayColor, setDetectedOverlayColor ] = useState();
// Turn on contrast checker for web only since it's not supported on mobile yet.
const enableContrastChecking = Platform.OS === 'web';
useEffect( () => {
if ( ! enableContrastChecking ) {
return;
}
detectColors(
navRef.current,
setDetectedColor,
setDetectedBackgroundColor
);

const subMenuElement = navRef.current?.querySelector(
'[data-type="core/navigation-submenu"] [data-type="core/navigation-link"]'
);

if ( ! subMenuElement ) {
return;
}

// Only detect submenu overlay colors if they have previously been explicitly set.
// This avoids the contrast checker from reporting on inherited submenu colors and
// showing the contrast warning twice.
if ( overlayTextColor.color || overlayBackgroundColor.color ) {
detectColors(
subMenuElement,
setDetectedOverlayColor,
setDetectedOverlayBackgroundColor
);
}
}, [
enableContrastChecking,
overlayTextColor.color,
overlayBackgroundColor.color,
navRef,
] );
const colorGradientSettings = useMultipleOriginColorsAndGradients();
if ( ! colorGradientSettings.hasColorsOrGradients ) {
return null;
}
return (
<>
<ColorGradientSettingsDropdown
__experimentalIsRenderedInSidebar
settings={ [
{
colorValue: textColor.color,
label: __( 'Text' ),
onColorChange: setTextColor,
resetAllFilter: () => setTextColor(),
},
{
colorValue: backgroundColor.color,
label: __( 'Background' ),
onColorChange: setBackgroundColor,
resetAllFilter: () => setBackgroundColor(),
},
{
colorValue: overlayTextColor.color,
label: __( 'Submenu & overlay text' ),
onColorChange: setOverlayTextColor,
resetAllFilter: () => setOverlayTextColor(),
},
{
colorValue: overlayBackgroundColor.color,
label: __( 'Submenu & overlay background' ),
onColorChange: setOverlayBackgroundColor,
resetAllFilter: () => setOverlayBackgroundColor(),
},
] }
panelId={ clientId }
{ ...colorGradientSettings }
gradients={ [] }
disableCustomGradients
/>
{ enableContrastChecking && (
<>
<ContrastChecker
backgroundColor={ detectedBackgroundColor }
textColor={ detectedColor }
/>
<ContrastChecker
backgroundColor={ detectedOverlayBackgroundColor }
textColor={ detectedOverlayColor }
/>
</>
) }
</>
);
}

function Navigation( {
attributes,
setAttributes,
Expand Down Expand Up @@ -330,17 +440,6 @@ function Navigation( {
},
} );

// Turn on contrast checker for web only since it's not supported on mobile yet.
const enableContrastChecking = Platform.OS === 'web';

const [ detectedBackgroundColor, setDetectedBackgroundColor ] = useState();
const [ detectedColor, setDetectedColor ] = useState();
const [
detectedOverlayBackgroundColor,
setDetectedOverlayBackgroundColor,
] = useState();
const [ detectedOverlayColor, setDetectedOverlayColor ] = useState();

const onSelectClassicMenu = async ( classicMenu ) => {
return convertClassicMenu( classicMenu.id, classicMenu.name, 'draft' );
};
Expand Down Expand Up @@ -412,40 +511,6 @@ function Navigation( {
handleUpdateMenu,
] );

useEffect( () => {
if ( ! enableContrastChecking ) {
return;
}
detectColors(
navRef.current,
setDetectedColor,
setDetectedBackgroundColor
);

const subMenuElement = navRef.current?.querySelector(
'[data-type="core/navigation-submenu"] [data-type="core/navigation-link"]'
);

if ( ! subMenuElement ) {
return;
}

// Only detect submenu overlay colors if they have previously been explicitly set.
// This avoids the contrast checker from reporting on inherited submenu colors and
// showing the contrast warning twice.
if ( overlayTextColor.color || overlayBackgroundColor.color ) {
detectColors(
subMenuElement,
setDetectedOverlayColor,
setDetectedOverlayBackgroundColor
);
}
}, [
enableContrastChecking,
overlayTextColor.color,
overlayBackgroundColor.color,
] );

useEffect( () => {
if ( ! isSelected && ! isInnerBlockSelected ) {
hideNavigationMenuPermissionsNotice();
Expand Down Expand Up @@ -518,7 +583,6 @@ function Navigation( {
`overlay-menu-preview`
);

const colorGradientSettings = useMultipleOriginColorsAndGradients();
const stylingInspectorControls = (
<>
<InspectorControls>
Expand Down Expand Up @@ -634,58 +698,25 @@ function Navigation( {
</PanelBody>
) }
</InspectorControls>
{ colorGradientSettings.hasColorsOrGradients && (
<InspectorControls group="color">
<ColorGradientSettingsDropdown
__experimentalIsRenderedInSidebar
settings={ [
{
colorValue: textColor.color,
label: __( 'Text' ),
onColorChange: setTextColor,
resetAllFilter: () => setTextColor(),
},
{
colorValue: backgroundColor.color,
label: __( 'Background' ),
onColorChange: setBackgroundColor,
resetAllFilter: () => setBackgroundColor(),
},
{
colorValue: overlayTextColor.color,
label: __( 'Submenu & overlay text' ),
onColorChange: setOverlayTextColor,
resetAllFilter: () => setOverlayTextColor(),
},
{
colorValue: overlayBackgroundColor.color,
label: __( 'Submenu & overlay background' ),
onColorChange: setOverlayBackgroundColor,
resetAllFilter: () =>
setOverlayBackgroundColor(),
},
] }
panelId={ clientId }
{ ...colorGradientSettings }
gradients={ [] }
disableCustomGradients
/>
{ enableContrastChecking && (
<>
<ContrastChecker
backgroundColor={ detectedBackgroundColor }
textColor={ detectedColor }
/>
<ContrastChecker
backgroundColor={
detectedOverlayBackgroundColor
}
textColor={ detectedOverlayColor }
/>
</>
) }
</InspectorControls>
) }
<InspectorControls group="color">
{ /*
* Avoid useMultipleOriginColorsAndGradients and detectColors
* on block mount. InspectorControls only mounts this component
* when the block is selected.
* */ }
<ColorTools
textColor={ textColor }
setTextColor={ setTextColor }
backgroundColor={ backgroundColor }
setBackgroundColor={ setBackgroundColor }
overlayTextColor={ overlayTextColor }
setOverlayTextColor={ setOverlayTextColor }
overlayBackgroundColor={ overlayBackgroundColor }
setOverlayBackgroundColor={ setOverlayBackgroundColor }
clientId={ clientId }
navRef={ navRef }
/>
</InspectorControls>
</>
);

Expand Down
Loading