diff --git a/docs/reference-guides/block-api/block-supports.md b/docs/reference-guides/block-api/block-supports.md index 1be449255d2da0..2e3e972e52037f 100644 --- a/docs/reference-guides/block-api/block-supports.md +++ b/docs/reference-guides/block-api/block-supports.md @@ -585,4 +585,4 @@ supports: { } ``` -A spacing property may define an array of allowable sides that can be configured. When arbitrary sides are defined only UI controls for those sides are displayed. +A spacing property may define an array of allowable sides that can be configured. When arbitrary sides are defined only UI controls for those sides are displayed. Axial sides are defined with the `vertical` and `horizontal` terms, and display a single UI control for each axial pair (for example, `vertical` controls both the top and bottom sides). A spacing property may support arbitrary individual sides **or** axial sides, but not a mix of both. diff --git a/packages/block-editor/src/hooks/dimensions.js b/packages/block-editor/src/hooks/dimensions.js index 8351676640b177..697955670b497e 100644 --- a/packages/block-editor/src/hooks/dimensions.js +++ b/packages/block-editor/src/hooks/dimensions.js @@ -30,6 +30,8 @@ import { import { cleanEmptyObject } from './utils'; export const SPACING_SUPPORT_KEY = 'spacing'; +export const ALL_SIDES = [ 'top', 'right', 'bottom', 'left' ]; +export const AXIAL_SIDES = [ 'vertical', 'horizontal' ]; /** * Inspector controls for dimensions support. @@ -146,9 +148,37 @@ export function useCustomSides( blockName, feature ) { const support = getBlockSupport( blockName, SPACING_SUPPORT_KEY ); // Skip when setting is boolean as theme isn't setting arbitrary sides. - if ( typeof support[ feature ] === 'boolean' ) { + if ( ! support || typeof support[ feature ] === 'boolean' ) { return; } return support[ feature ]; } + +/** + * Custom hook to determine whether the sides configured in the + * block support are valid. A dimension property cannot declare + * support for a mix of axial and individual sides. + * + * @param {string} blockName Block name. + * @param {string} feature The feature custom sides relate to e.g. padding or margins. + * + * @return {boolean} If the feature has a valid configuration of sides. + */ +export function useIsDimensionsSupportValid( blockName, feature ) { + const sides = useCustomSides( blockName, feature ); + + if ( + sides && + sides.some( ( side ) => ALL_SIDES.includes( side ) ) && + sides.some( ( side ) => AXIAL_SIDES.includes( side ) ) + ) { + // eslint-disable-next-line no-console + console.warn( + `The ${ feature } support for the "${ blockName }" block can not be configured to support both axial and arbitrary sides.` + ); + return false; + } + + return true; +} diff --git a/packages/block-editor/src/hooks/margin.js b/packages/block-editor/src/hooks/margin.js index 7e89049b40846b..1dfe87c96ca7dc 100644 --- a/packages/block-editor/src/hooks/margin.js +++ b/packages/block-editor/src/hooks/margin.js @@ -13,7 +13,12 @@ import { * Internal dependencies */ import useSetting from '../components/use-setting'; -import { SPACING_SUPPORT_KEY, useCustomSides } from './dimensions'; +import { + AXIAL_SIDES, + SPACING_SUPPORT_KEY, + useCustomSides, + useIsDimensionsSupportValid, +} from './dimensions'; import { cleanEmptyObject } from './utils'; /** @@ -69,7 +74,9 @@ export function resetMargin( { attributes = {}, setAttributes } ) { */ export function useIsMarginDisabled( { name: blockName } = {} ) { const isDisabled = ! useSetting( 'spacing.customMargin' ); - return ! hasMarginSupport( blockName ) || isDisabled; + const isInvalid = ! useIsDimensionsSupportValid( blockName, 'margin' ); + + return ! hasMarginSupport( blockName ) || isDisabled || isInvalid; } /** @@ -96,6 +103,8 @@ export function MarginEdit( props ) { ], } ); const sides = useCustomSides( blockName, 'margin' ); + const splitOnAxis = + sides && sides.some( ( side ) => AXIAL_SIDES.includes( side ) ); if ( useIsMarginDisabled( props ) ) { return null; @@ -139,6 +148,7 @@ export function MarginEdit( props ) { sides={ sides } units={ units } allowReset={ false } + splitOnAxis={ splitOnAxis } /> ), diff --git a/packages/block-editor/src/hooks/padding.js b/packages/block-editor/src/hooks/padding.js index e481946e3defc0..717c69a401e60b 100644 --- a/packages/block-editor/src/hooks/padding.js +++ b/packages/block-editor/src/hooks/padding.js @@ -13,7 +13,12 @@ import { * Internal dependencies */ import useSetting from '../components/use-setting'; -import { SPACING_SUPPORT_KEY, useCustomSides } from './dimensions'; +import { + AXIAL_SIDES, + SPACING_SUPPORT_KEY, + useCustomSides, + useIsDimensionsSupportValid, +} from './dimensions'; import { cleanEmptyObject } from './utils'; /** @@ -69,7 +74,9 @@ export function resetPadding( { attributes = {}, setAttributes } ) { */ export function useIsPaddingDisabled( { name: blockName } = {} ) { const isDisabled = ! useSetting( 'spacing.customPadding' ); - return ! hasPaddingSupport( blockName ) || isDisabled; + const isInvalid = ! useIsDimensionsSupportValid( blockName, 'padding' ); + + return ! hasPaddingSupport( blockName ) || isDisabled || isInvalid; } /** @@ -96,6 +103,8 @@ export function PaddingEdit( props ) { ], } ); const sides = useCustomSides( blockName, 'padding' ); + const splitOnAxis = + sides && sides.some( ( side ) => AXIAL_SIDES.includes( side ) ); if ( useIsPaddingDisabled( props ) ) { return null; @@ -139,6 +148,7 @@ export function PaddingEdit( props ) { sides={ sides } units={ units } allowReset={ false } + splitOnAxis={ splitOnAxis } /> ), diff --git a/packages/block-library/src/button/block.json b/packages/block-library/src/button/block.json index d954cc3c40e991..569ecc47fd0e72 100644 --- a/packages/block-library/src/button/block.json +++ b/packages/block-library/src/button/block.json @@ -68,7 +68,10 @@ "reusable": false, "spacing": { "__experimentalSkipSerialization": true, - "padding": true + "padding": [ "horizontal", "vertical" ], + "__experimentalDefaultControls": { + "padding": true + } }, "__experimentalBorder": { "radius": true, diff --git a/packages/edit-site/src/components/sidebar/dimensions-panel.js b/packages/edit-site/src/components/sidebar/dimensions-panel.js index 4f19f7e19cae6d..05b4aadd2d5bf0 100644 --- a/packages/edit-site/src/components/sidebar/dimensions-panel.js +++ b/packages/edit-site/src/components/sidebar/dimensions-panel.js @@ -15,6 +15,8 @@ import { __experimentalUseCustomSides as useCustomSides } from '@wordpress/block */ import { useSetting } from '../editor/utils'; +const AXIAL_SIDES = [ 'horizontal', 'vertical' ]; + export function useHasDimensionsPanel( context ) { const hasPadding = useHasPadding( context ); const hasMargin = useHasMargin( context ); @@ -42,7 +44,17 @@ function filterValuesBySides( values, sides ) { // Only include sides opted into within filtered values. const filteredValues = {}; - sides.forEach( ( side ) => ( filteredValues[ side ] = values[ side ] ) ); + sides.forEach( ( side ) => { + if ( side === 'vertical' ) { + filteredValues.top = values.top; + filteredValues.bottom = values.bottom; + } + if ( side === 'horizontal' ) { + filteredValues.left = values.left; + filteredValues.right = values.right; + } + filteredValues[ side ] = values[ side ]; + } ); return filteredValues; } @@ -78,6 +90,9 @@ export default function DimensionsPanel( { context, getStyle, setStyle } ) { const paddingValues = splitStyleValue( getStyle( name, 'padding' ) ); const paddingSides = useCustomSides( name, 'padding' ); + const isAxialPadding = + paddingSides && + paddingSides.some( ( side ) => AXIAL_SIDES.includes( side ) ); const setPaddingValues = ( newPaddingValues ) => { const padding = filterValuesBySides( newPaddingValues, paddingSides ); @@ -89,6 +104,9 @@ export default function DimensionsPanel( { context, getStyle, setStyle } ) { const marginValues = splitStyleValue( getStyle( name, 'margin' ) ); const marginSides = useCustomSides( name, 'margin' ); + const isAxialMargin = + marginSides && + marginSides.some( ( side ) => AXIAL_SIDES.includes( side ) ); const setMarginValues = ( newMarginValues ) => { const margin = filterValuesBySides( newMarginValues, marginSides ); @@ -123,6 +141,7 @@ export default function DimensionsPanel( { context, getStyle, setStyle } ) { sides={ paddingSides } units={ units } allowReset={ false } + splitOnAxis={ isAxialPadding } /> ) } @@ -140,6 +159,7 @@ export default function DimensionsPanel( { context, getStyle, setStyle } ) { sides={ marginSides } units={ units } allowReset={ false } + splitOnAxis={ isAxialMargin } /> ) }