From 0d5bd300f0d191fe93e50eb3eb71d401865f300a Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 22 Oct 2021 14:30:35 +1000 Subject: [PATCH] Typography: Switch to ToolsPanel for block support UI (#33744) * Switch typography block support to use ToolsPanel * Update font size picker reset e2e tests for ToolsPanel --- .../src/components/block-inspector/index.js | 5 + packages/block-editor/src/components/index.js | 2 + .../components/inspector-controls/groups.js | 4 + .../text-decoration-and-transform/index.js | 36 ---- .../text-decoration-and-transform/style.scss | 3 - .../block-editor/src/hooks/font-appearance.js | 41 ++++- .../block-editor/src/hooks/font-family.js | 40 +++-- packages/block-editor/src/hooks/font-size.js | 48 ++++- .../block-editor/src/hooks/letter-spacing.js | 39 +++- .../block-editor/src/hooks/line-height.js | 44 ++++- .../block-editor/src/hooks/text-decoration.js | 38 +++- .../block-editor/src/hooks/text-transform.js | 38 +++- packages/block-editor/src/hooks/typography.js | 170 ++++++++++++++++-- .../block-editor/src/hooks/typography.scss | 12 ++ packages/block-editor/src/style.scss | 2 +- .../block-library/src/paragraph/block.json | 6 +- .../editor/various/font-size-picker.test.js | 35 ++-- 17 files changed, 444 insertions(+), 119 deletions(-) delete mode 100644 packages/block-editor/src/components/text-decoration-and-transform/index.js delete mode 100644 packages/block-editor/src/components/text-decoration-and-transform/style.scss create mode 100644 packages/block-editor/src/hooks/typography.scss diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index 584b600bc4d7dd..b7f85f4e5084e1 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -129,6 +129,11 @@ const BlockInspectorSingleBlock = ( { ) } + - { decorationAvailable && } - { transformAvailable && } - - ); -} diff --git a/packages/block-editor/src/components/text-decoration-and-transform/style.scss b/packages/block-editor/src/components/text-decoration-and-transform/style.scss deleted file mode 100644 index 3f62e923036a4b..00000000000000 --- a/packages/block-editor/src/components/text-decoration-and-transform/style.scss +++ /dev/null @@ -1,3 +0,0 @@ -.block-editor-text-decoration-and-transform { - display: flex; -} diff --git a/packages/block-editor/src/hooks/font-appearance.js b/packages/block-editor/src/hooks/font-appearance.js index 4bb7e593a4e0af..44c26d432bddfd 100644 --- a/packages/block-editor/src/hooks/font-appearance.js +++ b/packages/block-editor/src/hooks/font-appearance.js @@ -36,10 +36,6 @@ export function FontAppearanceEdit( props ) { const hasFontStyles = ! useIsFontStyleDisabled( props ); const hasFontWeights = ! useIsFontWeightDisabled( props ); - if ( ! hasFontStyles && ! hasFontWeights ) { - return null; - } - const onChange = ( newStyles ) => { setAttributes( { style: cleanEmptyObject( { @@ -54,7 +50,6 @@ export function FontAppearanceEdit( props ) { }; const fontStyle = style?.typography?.fontStyle; - const fontWeight = style?.typography?.fontWeight; return ( @@ -112,3 +107,39 @@ export function useIsFontAppearanceDisabled( props ) { return stylesDisabled && weightsDisabled; } + +/** + * Checks if there is either a font style or weight value set within the + * typography styles. + * + * @param {Object} props Block props. + * @return {boolean} Whether or not the block has a font style or weight. + */ +export function hasFontAppearanceValue( props ) { + const { fontStyle, fontWeight } = props.attributes.style?.typography || {}; + return !! fontStyle || !! fontWeight; +} + +/** + * Resets the font style and weight block support attributes. This can be used + * when disabling the font appearance support controls for a block via a + * progressive discovery panel. + * + * @param {Object} props Block props. + * @param {Object} props.attributes Block's attributes. + * @param {Object} props.setAttributes Function to set block's attributes. + */ +export function resetFontAppearance( { attributes = {}, setAttributes } ) { + const { style } = attributes; + + setAttributes( { + style: cleanEmptyObject( { + ...style, + typography: { + ...style?.typography, + fontStyle: undefined, + fontWeight: undefined, + }, + } ), + } ); +} diff --git a/packages/block-editor/src/hooks/font-family.js b/packages/block-editor/src/hooks/font-family.js index 769e424e540911..1ee11f6514b113 100644 --- a/packages/block-editor/src/hooks/font-family.js +++ b/packages/block-editor/src/hooks/font-family.js @@ -22,8 +22,8 @@ export const FONT_FAMILY_SUPPORT_KEY = 'typography.__experimentalFontFamily'; * Filters registered block settings, extending attributes to include * the `fontFamily` attribute. * - * @param {Object} settings Original block settings - * @return {Object} Filtered block settings + * @param {Object} settings Original block settings + * @return {Object} Filtered block settings */ function addAttributes( settings ) { if ( ! hasBlockSupport( settings, FONT_FAMILY_SUPPORT_KEY ) ) { @@ -45,10 +45,10 @@ function addAttributes( settings ) { /** * Override props assigned to save component to inject font family. * - * @param {Object} props Additional props applied to save element - * @param {Object} blockType Block type - * @param {Object} attributes Block attributes - * @return {Object} Filtered props applied to save element + * @param {Object} props Additional props applied to save element + * @param {Object} blockType Block type + * @param {Object} attributes Block attributes + * @return {Object} Filtered props applied to save element */ function addSaveProps( props, blockType, attributes ) { if ( ! hasBlockSupport( blockType, FONT_FAMILY_SUPPORT_KEY ) ) { @@ -103,16 +103,10 @@ function addEditProps( settings ) { } export function FontFamilyEdit( { - name, setAttributes, attributes: { fontFamily }, } ) { const fontFamilies = useSetting( 'typography.fontFamilies' ); - const isDisable = useIsFontFamilyDisabled( { name } ); - - if ( isDisable ) { - return null; - } const value = find( fontFamilies, ( { slug } ) => fontFamily === slug ) ?.fontFamily; @@ -152,6 +146,28 @@ export function useIsFontFamilyDisabled( { name } ) { ); } +/** + * Checks if there is a current value set for the font family block support. + * + * @param {Object} props Block props. + * @return {boolean} Whether or not the block has a font family value set. + */ +export function hasFontFamilyValue( props ) { + return !! props.attributes.fontFamily; +} + +/** + * Resets the font family block support attribute. This can be used when + * disabling the font family support controls for a block via a progressive + * discovery panel. + * + * @param {Object} props Block props. + * @param {Object} props.setAttributes Function to set block's attributes. + */ +export function resetFontFamily( { setAttributes } ) { + setAttributes( { fontFamily: undefined } ); +} + addFilter( 'blocks.registerBlockType', 'core/fontFamily/addAttribute', diff --git a/packages/block-editor/src/hooks/font-size.js b/packages/block-editor/src/hooks/font-size.js index 86624748a790bb..3a2abfbb85f255 100644 --- a/packages/block-editor/src/hooks/font-size.js +++ b/packages/block-editor/src/hooks/font-size.js @@ -114,7 +114,6 @@ export function FontSizeEdit( props ) { attributes: { fontSize, style }, setAttributes, } = props; - const isDisabled = useIsFontSizeDisabled( props ); const fontSizes = useSetting( 'typography.fontSizes' ); const onChange = ( value ) => { @@ -132,10 +131,6 @@ export function FontSizeEdit( props ) { } ); }; - if ( isDisabled ) { - return null; - } - const fontSizeObject = getFontSize( fontSizes, fontSize, @@ -145,7 +140,48 @@ export function FontSizeEdit( props ) { const fontSizeValue = fontSizeObject?.size || style?.typography?.fontSize || fontSize; - return ; + return ( + + ); +} + +/** + * Checks if there is a current value set for the font size block support. + * + * @param {Object} props Block props. + * @return {boolean} Whether or not the block has a font size value set. + */ +export function hasFontSizeValue( props ) { + const { fontSize, style } = props.attributes; + return !! fontSize || !! style?.typography?.fontSize; +} + +/** + * Resets the font size block support attribute. This can be used when + * disabling the font size support controls for a block via a progressive + * discovery panel. + * + * @param {Object} props Block props. + * @param {Object} props.attributes Block's attributes. + * @param {Object} props.setAttributes Function to set block's attributes. + */ +export function resetFontSize( { attributes = {}, setAttributes } ) { + const { style } = attributes; + + setAttributes( { + fontSize: undefined, + style: cleanEmptyObject( { + ...style, + typography: { + ...style?.typography, + fontSize: undefined, + }, + } ), + } ); } /** diff --git a/packages/block-editor/src/hooks/letter-spacing.js b/packages/block-editor/src/hooks/letter-spacing.js index 25369ae9daaa81..01446ef4024324 100644 --- a/packages/block-editor/src/hooks/letter-spacing.js +++ b/packages/block-editor/src/hooks/letter-spacing.js @@ -29,12 +29,6 @@ export function LetterSpacingEdit( props ) { setAttributes, } = props; - const isDisabled = useIsLetterSpacingDisabled( props ); - - if ( isDisabled ) { - return null; - } - function onChange( newSpacing ) { setAttributes( { style: cleanEmptyObject( { @@ -70,3 +64,36 @@ export function useIsLetterSpacingDisabled( { name: blockName } = {} ) { return notSupported || ! hasLetterSpacing; } + +/** + * Checks if there is a current value set for the letter spacing block support. + * + * @param {Object} props Block props. + * @return {boolean} Whether or not the block has a letter spacing set. + */ +export function hasLetterSpacingValue( props ) { + return !! props.attributes.style?.typography?.letterSpacing; +} + +/** + * Resets the letter spacing block support attribute. This can be used when + * disabling the letter spacing support controls for a block via a progressive + * discovery panel. + * + * @param {Object} props Block props. + * @param {Object} props.attributes Block's attributes. + * @param {Object} props.setAttributes Function to set block's attributes. + */ +export function resetLetterSpacing( { attributes = {}, setAttributes } ) { + const { style } = attributes; + + setAttributes( { + style: cleanEmptyObject( { + ...style, + typography: { + ...style?.typography, + letterSpacing: undefined, + }, + } ), + } ); +} diff --git a/packages/block-editor/src/hooks/line-height.js b/packages/block-editor/src/hooks/line-height.js index 1d57366878b214..c7ced1ac486238 100644 --- a/packages/block-editor/src/hooks/line-height.js +++ b/packages/block-editor/src/hooks/line-height.js @@ -22,12 +22,8 @@ export const LINE_HEIGHT_SUPPORT_KEY = 'typography.lineHeight'; export function LineHeightEdit( props ) { const { attributes: { style }, + setAttributes, } = props; - const isDisabled = useIsLineHeightDisabled( props ); - - if ( isDisabled ) { - return null; - } const onChange = ( newLineHeightValue ) => { const newStyle = { @@ -37,9 +33,8 @@ export function LineHeightEdit( props ) { lineHeight: newLineHeightValue, }, }; - props.setAttributes( { - style: cleanEmptyObject( newStyle ), - } ); + + setAttributes( { style: cleanEmptyObject( newStyle ) } ); }; return ( ( newAttributes ) => ( { + ...newAttributes, + style: { + ...newAttributes.style, + typography: { + ...newAttributes.style?.typography, + [ attribute ]: undefined, + }, + }, + } ); + return ( - - - - - - - - - + + { ! isFontFamilyDisabled && ( + hasFontFamilyValue( props ) } + label={ __( 'Font family' ) } + onDeselect={ () => resetFontFamily( props ) } + isShownByDefault={ defaultControls?.fontFamily } + resetAllFilter={ ( newAttributes ) => ( { + ...newAttributes, + fontFamily: undefined, + } ) } + panelId={ clientId } + > + + + ) } + { ! isFontSizeDisabled && ( + hasFontSizeValue( props ) } + label={ __( 'Font size' ) } + onDeselect={ () => resetFontSize( props ) } + isShownByDefault={ defaultControls?.fontSize } + resetAllFilter={ ( newAttributes ) => ( { + ...newAttributes, + fontSize: undefined, + style: { + ...newAttributes.style, + typography: { + ...newAttributes.style?.typography, + fontSize: undefined, + }, + }, + } ) } + panelId={ clientId } + > + + + ) } + { ! isFontAppearanceDisabled && ( + hasFontAppearanceValue( props ) } + label={ __( 'Appearance' ) } + onDeselect={ () => resetFontAppearance( props ) } + isShownByDefault={ defaultControls?.fontAppearance } + resetAllFilter={ ( newAttributes ) => ( { + ...newAttributes, + style: { + ...newAttributes.style, + typography: { + ...newAttributes.style?.typography, + fontStyle: undefined, + fontWeight: undefined, + }, + }, + } ) } + panelId={ clientId } + > + + + ) } + { ! isLineHeightDisabled && ( + hasLineHeightValue( props ) } + label={ __( 'Line height' ) } + onDeselect={ () => resetLineHeight( props ) } + isShownByDefault={ defaultControls?.lineHeight } + resetAllFilter={ createResetAllFilter( 'lineHeight' ) } + panelId={ clientId } + > + + + ) } + { ! isTextDecorationDisabled && ( + hasTextDecorationValue( props ) } + label={ __( 'Decoration' ) } + onDeselect={ () => resetTextDecoration( props ) } + isShownByDefault={ defaultControls?.textDecoration } + resetAllFilter={ createResetAllFilter( 'textDecoration' ) } + panelId={ clientId } + > + + + ) } + { ! isTextTransformDisabled && ( + hasTextTransformValue( props ) } + label={ __( 'Letter case' ) } + onDeselect={ () => resetTextTransform( props ) } + isShownByDefault={ defaultControls?.textTransform } + resetAllFilter={ createResetAllFilter( 'textTransform' ) } + panelId={ clientId } + > + + + ) } + { ! isLetterSpacingDisabled && ( + hasLetterSpacingValue( props ) } + label={ __( 'Letter-spacing' ) } + onDeselect={ () => resetLetterSpacing( props ) } + isShownByDefault={ defaultControls?.letterSpacing } + resetAllFilter={ createResetAllFilter( 'letterSpacing' ) } + panelId={ clientId } + > + + + ) } ); } diff --git a/packages/block-editor/src/hooks/typography.scss b/packages/block-editor/src/hooks/typography.scss new file mode 100644 index 00000000000000..293b66d7540537 --- /dev/null +++ b/packages/block-editor/src/hooks/typography.scss @@ -0,0 +1,12 @@ +.typography-block-support-panel { + .components-font-appearance-control, + .components-font-size-picker__controls, + .block-editor-text-decoration-control__buttons, + .block-editor-text-transform-control__buttons { + margin-bottom: 0; + } + + .block-editor-line-height-control input { + max-width: 100%; + } +} diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 22a48857359ac7..de72069bcde141 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -46,7 +46,6 @@ @import "./components/responsive-block-control/style.scss"; @import "./components/rich-text/style.scss"; @import "./components/skip-to-selected-block/style.scss"; -@import "./components/text-decoration-and-transform/style.scss"; @import "./components/text-transform-control/style.scss"; @import "./components/text-decoration-control/style.scss"; @import "./components/tool-selector/style.scss"; @@ -56,6 +55,7 @@ @import "./hooks/anchor.scss"; @import "./hooks/layout.scss"; @import "./hooks/border.scss"; +@import "./hooks/typography.scss"; @import "./components/block-toolbar/style.scss"; @import "./components/inserter/style.scss"; diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json index d05e48a7bebe23..d024ee2a8fce15 100644 --- a/packages/block-library/src/paragraph/block.json +++ b/packages/block-library/src/paragraph/block.json @@ -37,7 +37,11 @@ }, "typography": { "fontSize": true, - "lineHeight": true + "lineHeight": true, + "__experimentalDefaultControls": { + "fontSize": true, + "lineHeight": true + } }, "__experimentalSelector": "p", "__unstablePasteTextInline": true diff --git a/packages/e2e-tests/specs/editor/various/font-size-picker.test.js b/packages/e2e-tests/specs/editor/various/font-size-picker.test.js index c2e9bceed1de26..7e405330fb717c 100644 --- a/packages/e2e-tests/specs/editor/various/font-size-picker.test.js +++ b/packages/e2e-tests/specs/editor/various/font-size-picker.test.js @@ -17,6 +17,13 @@ const openFontSizeSelectControl = async () => { return selectControl.click(); }; +const openTypographyToolsPanelMenu = async () => { + const toggleSelector = + "//div[contains(@class, 'typography-block-support-panel')]//button[contains(@class, 'components-dropdown-menu__toggle')]"; + const toggle = await page.waitForXPath( toggleSelector ); + return toggle.click(); +}; + const FONT_SIZE_TOGGLE_GROUP_SELECTOR = "//div[contains(@class, 'components-font-size-picker__controls')]//div[contains(@class, 'components-toggle-group-control')]"; @@ -122,11 +129,11 @@ describe( 'Font Size Picker', () => { " ` ); } ); - it( 'should reset a named font size using the reset button', async () => { + it( 'should reset a named font size using the tools panel menu', async () => { // Create a paragraph block with some content. await clickBlockAppender(); await page.keyboard.type( - 'Paragraph with font size reset using button' + 'Paragraph with font size reset using tools panel menu' ); await openFontSizeSelectControl(); @@ -134,19 +141,17 @@ describe( 'Font Size Picker', () => { await page.keyboard.press( 'Enter' ); expect( await getEditedPostContent() ).toMatchInlineSnapshot( ` " -

Paragraph with font size reset using button

+

Paragraph with font size reset using tools panel menu

" ` ); - await toggleCustomInput( true ); - await page.keyboard.press( 'Tab' ); - await page.keyboard.press( 'Tab' ); - await page.keyboard.press( 'Tab' ); + // Open Typography ToolsPanel, font size will be first in menu and gain focus. + await openTypographyToolsPanelMenu(); await page.keyboard.press( 'Enter' ); expect( await getEditedPostContent() ).toMatchInlineSnapshot( ` " -

Paragraph with font size reset using button

+

Paragraph with font size reset using tools panel menu

" ` ); } ); @@ -205,29 +210,27 @@ describe( 'Font Size Picker', () => { ` ); } ); - it( 'should reset a named font size using the reset button', async () => { + it( 'should reset a named font size using the tools panel menu', async () => { // Create a paragraph block with some content. await clickBlockAppender(); await page.keyboard.type( - 'Paragraph with font size reset using button' + 'Paragraph with font size reset using tools panel menu' ); await clickFontSizeButtonByLabel( 'Small' ); expect( await getEditedPostContent() ).toMatchInlineSnapshot( ` " -

Paragraph with font size reset using button

+

Paragraph with font size reset using tools panel menu

" ` ); - await toggleCustomInput( true ); - await page.keyboard.press( 'Tab' ); - await page.keyboard.press( 'Tab' ); - await page.keyboard.press( 'Tab' ); + // Open Typography ToolsPanel, font size will be first in menu and gain focus. + await openTypographyToolsPanelMenu(); await page.keyboard.press( 'Enter' ); expect( await getEditedPostContent() ).toMatchInlineSnapshot( ` " -

Paragraph with font size reset using button

+

Paragraph with font size reset using tools panel menu

" ` ); } );