diff --git a/packages/block-editor/src/hooks/block-style-variation.js b/packages/block-editor/src/hooks/block-style-variation.js index f00c96d640a575..21259966d8a63b 100644 --- a/packages/block-editor/src/hooks/block-style-variation.js +++ b/packages/block-editor/src/hooks/block-style-variation.js @@ -69,18 +69,14 @@ function OverrideStyles( { override } ) { * This component is used to generate new block style variation overrides * based on an incoming theme config. If a matching style is found in the config, * a new override is created and returned. The overrides can be used in conjunction with - * useStyleOverride to apply the new styles to the editor. - * NOTE: This component is required to load global styles revisions config. Style variation overrides are - * generated using the canvas's current global styles (see useBlockStyleVariation()). This component is, - * however, due to be refactored and therefore it's use elsewhere is not recommended. + * useStyleOverride to apply the new styles to the editor. Its use is + * subject to change. * * @param {Object} props Props. * @param {Object} props.config A global styles object, containing settings and styles. - * @return {JSX.Element} An array of new block variation overrides. + * @return {JSX.Element|undefined} An array of new block variation overrides. */ -export function ExperimentalBlockStyleVariationOverridesWithConfig( { - config, -} ) { +export function __unstableBlockStyleVariationOverridesWithConfig( { config } ) { const { getBlockStyles, overrides } = useSelect( ( select ) => ( { getBlockStyles: select( blocksStore ).getBlockStyles, @@ -91,8 +87,11 @@ export function ExperimentalBlockStyleVariationOverridesWithConfig( { const { getBlockName } = useSelect( blockEditorStore ); const overridesWithConfig = useMemo( () => { + if ( ! overrides?.length ) { + return; + } const newOverrides = []; - const clientIds = []; + const overriddenClientIds = []; for ( const [ , override ] of overrides ) { if ( override?.variation && @@ -101,7 +100,7 @@ export function ExperimentalBlockStyleVariationOverridesWithConfig( { * Because this component overwrites existing style overrides, * filter out any overrides that are already present in the store. */ - ! clientIds.includes( override.clientId ) + ! overriddenClientIds.includes( override.clientId ) ) { const blockName = getBlockName( override.clientId ); const configStyles = @@ -161,12 +160,16 @@ export function ExperimentalBlockStyleVariationOverridesWithConfig( { // correct CSS cascade is maintained. clientId: override.clientId, } ); - clientIds.push( override.clientId ); + overriddenClientIds.push( override.clientId ); } } } return newOverrides; - }, [ config, overrides, getBlockStyles ] ); + }, [ config, overrides, getBlockStyles, getBlockName ] ); + + if ( ! overridesWithConfig || ! overridesWithConfig.length ) { + return; + } return ( <> diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 6e79d2b3dbab86..bd1835571fdd4a 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -88,4 +88,4 @@ export { getTypographyClassesAndStyles } from './use-typography-props'; export { getGapCSSValue } from './gap'; export { useCachedTruthy } from './use-cached-truthy'; export { useZoomOut } from './use-zoom-out'; -export { ExperimentalBlockStyleVariationOverridesWithConfig } from './block-style-variation'; +export { __unstableBlockStyleVariationOverridesWithConfig } from './block-style-variation'; diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index b408693e375345..bfa6ac0c90c846 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -23,7 +23,7 @@ import { BlockRemovalWarningModal } from './components/block-removal-warning-mod import { useLayoutClasses, useLayoutStyles, - ExperimentalBlockStyleVariationOverridesWithConfig, + __unstableBlockStyleVariationOverridesWithConfig, } from './hooks'; import DimensionsTool from './components/dimensions-tool'; import ResolutionTool from './components/resolution-tool'; @@ -92,5 +92,5 @@ lock( privateApis, { PrivatePublishDateTimePicker, useSpacingSizes, useBlockDisplayTitle, - ExperimentalBlockStyleVariationOverridesWithConfig, + __unstableBlockStyleVariationOverridesWithConfig, } ); diff --git a/packages/edit-site/src/components/revisions/index.js b/packages/edit-site/src/components/revisions/index.js index 932905a8effd08..d43b5e8d2ac025 100644 --- a/packages/edit-site/src/components/revisions/index.js +++ b/packages/edit-site/src/components/revisions/index.js @@ -25,7 +25,7 @@ const { ExperimentalBlockEditorProvider, GlobalStylesContext, useGlobalStylesOutputWithConfig, - ExperimentalBlockStyleVariationOverridesWithConfig, + __unstableBlockStyleVariationOverridesWithConfig, } = unlock( blockEditorPrivateApis ); const { mergeBaseAndUserConfigs } = unlock( editorPrivateApis ); @@ -93,7 +93,7 @@ function Revisions( { userConfig, blocks } ) { * so they can access any registered style overrides. */ } - diff --git a/test/e2e/specs/site-editor/block-style-variations.spec.js b/test/e2e/specs/site-editor/block-style-variations.spec.js index 88539c844a6a89..fedcd0946eac86 100644 --- a/test/e2e/specs/site-editor/block-style-variations.spec.js +++ b/test/e2e/specs/site-editor/block-style-variations.spec.js @@ -16,7 +16,6 @@ test.describe( 'Block Style Variations', () => { requestUtils.activateTheme( 'gutenberg-test-themes/style-variations' ), - requestUtils.deleteAllPages(), ] ); stylesPostId = await requestUtils.getCurrentThemeGlobalStylesPostId(); } ); @@ -57,32 +56,43 @@ test.describe( 'Block Style Variations', () => { await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Block Style Variation A' } ) - .click( { force: true } ); + .click(); - // Check parent styles. + // Check parent styles have variation A styles. await expect( firstGroup ).toHaveCSS( 'border-style', 'dotted' ); await expect( firstGroup ).toHaveCSS( 'border-width', '1px' ); - // Check nested child and grandchild group block inherited styles. + // Check nested child and grandchild group block variation A inherited styles. await expect( secondGroup ).toHaveCSS( 'border-style', 'solid' ); await expect( secondGroup ).toHaveCSS( 'border-width', '11px' ); await expect( thirdGroup ).toHaveCSS( 'border-style', 'solid' ); await expect( thirdGroup ).toHaveCSS( 'border-width', '11px' ); - // Apply a block style to the first, nested Group block. + // Apply a block style to the nested child Group block. await editor.selectBlocks( secondGroup ); await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Block Style Variation B' } ) - .click( { force: true } ); + .click(); - // Check nested child styles. + // Check nested child styles have variation B styles. await expect( secondGroup ).toHaveCSS( 'border-style', 'dashed' ); await expect( secondGroup ).toHaveCSS( 'border-width', '2px' ); - // Check nested grandchild group block inherited styles. + // Check nested grandchild Group block variation B inherited styles. await expect( thirdGroup ).toHaveCSS( 'border-style', 'groove' ); await expect( thirdGroup ).toHaveCSS( 'border-width', '22px' ); + + // Apply a block style to the nested grandchild Group block. + await editor.selectBlocks( thirdGroup ); + await page.getByRole( 'tab', { name: 'Styles' } ).click(); + await page + .getByRole( 'button', { name: 'Block Style Variation A' } ) + .click(); + + // Check that the child's inner block styles from variation B are overridden by the grandchild's block style variation A. + await expect( thirdGroup ).toHaveCSS( 'border-style', 'dotted' ); + await expect( thirdGroup ).toHaveCSS( 'border-width', '1px' ); } ); test( 'update block style variations in global styles and check revisions match styles', async ( { @@ -108,16 +118,17 @@ test.describe( 'Block Style Variations', () => { await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Block Style Variation A' } ) - .click( { force: true } ); + .click(); // Apply a block style to the first, nested Group block. await editor.selectBlocks( secondGroup ); await page.getByRole( 'tab', { name: 'Styles' } ).click(); await page .getByRole( 'button', { name: 'Block Style Variation B' } ) - .click( { force: true } ); + .click(); // Update user global styles with new block style variation values. + // First revision. await siteEditorBlockStyleVariations.saveRevision( stylesPostId, { blocks: { 'core/group': { @@ -138,14 +149,41 @@ test.describe( 'Block Style Variations', () => { }, }, } ); + // The save button has been re-enabled. + await expect( + page + .getByRole( 'region', { name: 'Editor top bar' } ) + .getByRole( 'button', { name: 'Save' } ) + ).toBeEnabled(); + // Second revision (current). + await siteEditorBlockStyleVariations.saveRevision( stylesPostId, { + blocks: { + 'core/group': { + variations: { + 'block-style-variation-a': { + border: { + width: '7px', + style: 'dotted', + }, + }, + 'block-style-variation-b': { + border: { + width: '8px', + style: 'dotted', + }, + }, + }, + }, + }, + } ); // Check parent styles. - await expect( firstGroup ).toHaveCSS( 'border-style', 'outset' ); - await expect( firstGroup ).toHaveCSS( 'border-width', '3px' ); + await expect( firstGroup ).toHaveCSS( 'border-style', 'dotted' ); + await expect( firstGroup ).toHaveCSS( 'border-width', '7px' ); // Check nested child styles. - await expect( secondGroup ).toHaveCSS( 'border-style', 'double' ); - await expect( secondGroup ).toHaveCSS( 'border-width', '4px' ); + await expect( secondGroup ).toHaveCSS( 'border-style', 'dotted' ); + await expect( secondGroup ).toHaveCSS( 'border-width', '8px' ); // Check nested grandchild group block inherited styles. await expect( thirdGroup ).toHaveCSS( 'border-style', 'groove' ); @@ -182,21 +220,46 @@ test.describe( 'Block Style Variations', () => { .locator( '[data-type="core/group"]' ) .nth( 2 ); - // Check parent styles. + // Check parent styles have current revision. await expect( revisionFirstGroup ).toHaveCSS( 'border-style', - 'outset' + 'dotted' + ); + await expect( revisionFirstGroup ).toHaveCSS( 'border-width', '7px' ); + + // Check nested child styles have current revision. + await expect( revisionSecondGroup ).toHaveCSS( + 'border-style', + 'dotted' ); + await expect( revisionSecondGroup ).toHaveCSS( 'border-width', '8px' ); + + // Check nested grandchild group block inherited styles from current revision. + await expect( revisionThirdGroup ).toHaveCSS( + 'border-style', + 'groove' + ); + await expect( revisionThirdGroup ).toHaveCSS( 'border-width', '22px' ); + + // Click on previous revision. + await page + .getByRole( 'button', { + name: /^Changes saved by /, + } ) + .nth( 1 ) + .click(); + + // Check parent styles have previous revision. await expect( revisionFirstGroup ).toHaveCSS( 'border-width', '3px' ); - // Check nested child styles. + // Check nested child style have previous revision. await expect( revisionSecondGroup ).toHaveCSS( 'border-style', 'double' ); await expect( revisionSecondGroup ).toHaveCSS( 'border-width', '4px' ); - // Check nested grandchild group block inherited styles. + // Check nested grandchild group block inherited styles from previous revision. await expect( revisionThirdGroup ).toHaveCSS( 'border-style', 'groove'