diff --git a/packages/block-editor/src/hooks/padding.js b/packages/block-editor/src/hooks/padding.js
index 7253ee0629b66..f476a03ce3bfb 100644
--- a/packages/block-editor/src/hooks/padding.js
+++ b/packages/block-editor/src/hooks/padding.js
@@ -9,16 +9,33 @@ import { __experimentalBoxControl as BoxControl } from '@wordpress/components';
/**
* Internal dependencies
*/
+import useEditorFeature from '../components/use-editor-feature';
+import { SPACING_SUPPORT_KEY, useCustomSides } from './spacing';
import { cleanEmptyObject } from './utils';
import { useCustomUnits } from '../components/unit-control';
-export const SPACING_SUPPORT_KEY = 'spacing';
-
-const hasPaddingSupport = ( blockName ) => {
- const spacingSupport = getBlockSupport( blockName, SPACING_SUPPORT_KEY );
- return spacingSupport && spacingSupport.padding !== false;
+/**
+ * Determines if there is padding support.
+ *
+ * @param {string|Object} blockType Block name or Block Type object.
+ * @return {boolean} Whether there is support.
+ */
+const hasPaddingSupport = ( blockType ) => {
+ const support = getBlockSupport( blockType, SPACING_SUPPORT_KEY );
+ return !! ( true === support || support?.padding );
};
+/**
+ * Custom hook that checks if padding settings have been disabled.
+ *
+ * @param {string} name The name of the block.
+ * @return {boolean} Whether padding setting is disabled.
+ */
+export function useIsPaddingDisabled( { name: blockName } = {} ) {
+ const isDisabled = ! useEditorFeature( 'spacing.customPadding' );
+ return ! hasPaddingSupport( blockName ) || isDisabled;
+}
+
/**
* Inspector control panel containing the padding related configuration
*
@@ -34,6 +51,7 @@ export function PaddingEdit( props ) {
} = props;
const units = useCustomUnits();
+ const sides = useCustomSides( blockName, 'padding' );
if ( ! hasPaddingSupport( blockName ) ) {
return null;
@@ -43,6 +61,7 @@ export function PaddingEdit( props ) {
const newStyle = {
...style,
spacing: {
+ ...style?.spacing,
padding: next,
},
};
@@ -73,6 +92,7 @@ export function PaddingEdit( props ) {
onChange={ onChange }
onChangeShowVisualizer={ onChangeShowVisualizer }
label={ __( 'Padding' ) }
+ sides={ sides }
units={ units }
/>
>
diff --git a/packages/block-editor/src/hooks/spacing.js b/packages/block-editor/src/hooks/spacing.js
new file mode 100644
index 0000000000000..49d2ee7283f75
--- /dev/null
+++ b/packages/block-editor/src/hooks/spacing.js
@@ -0,0 +1,85 @@
+/**
+ * WordPress dependencies
+ */
+import { getBlockSupport } from '@wordpress/blocks';
+import { Platform } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import { PaddingEdit, useIsPaddingDisabled } from './padding';
+import SpacingPanelControl from '../components/spacing-panel-control';
+
+export const SPACING_SUPPORT_KEY = 'spacing';
+
+/**
+ * Inspector controls for spacing support.
+ *
+ * @param {Object} props Block props.
+ * @return {WPElement} Inspector controls for spacing support features.
+ */
+export function SpacingPanel( props ) {
+ const isDisabled = useIsSpacingDisabled( props );
+ const isSupported = hasSpacingSupport( props.name );
+
+ if ( isDisabled || ! isSupported ) {
+ return null;
+ }
+
+ return (
+
+
+
+ );
+}
+
+/**
+ * Determine whether there is block support for padding or margins.
+ *
+ * @param {string} blockName Block name.
+ * @return {boolean} Whether there is support.
+ */
+export function hasSpacingSupport( blockName ) {
+ if ( Platform.OS !== 'web' ) {
+ return false;
+ }
+
+ const support = getBlockSupport( blockName, SPACING_SUPPORT_KEY );
+
+ return !! ( true === support || support?.padding || support?.margin );
+}
+
+/**
+ * Determines whether spacing support has been disabled.
+ *
+ * @param {Object} props Block properties.
+ * @return {boolean} If spacing support is completely disabled.
+ */
+const useIsSpacingDisabled = ( props = {} ) => {
+ const paddingDisabled = useIsPaddingDisabled( props );
+
+ return paddingDisabled;
+};
+
+/**
+ * Custom hook to retrieve which padding/margin is supported
+ * e.g. top, right, bottom or left.
+ *
+ * Sides are opted into by default. It is only if a specific side is set to
+ * false that it is omitted.
+ *
+ * @param {string} blockName Block name.
+ * @param {string} feature The feature custom sides relate to e.g. padding or margins.
+ * @return {Object} Sides supporting custom margin.
+ */
+export function useCustomSides( blockName, feature ) {
+ const support = getBlockSupport( blockName, SPACING_SUPPORT_KEY );
+
+ // Return empty config when setting is boolean as theme isn't setting
+ // arbitrary sides.
+ if ( typeof support[ feature ] === 'boolean' ) {
+ return {};
+ }
+
+ return support[ feature ];
+}
diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js
index b1c7239b2d791..8bbd8dba1e5fc 100644
--- a/packages/block-editor/src/hooks/style.js
+++ b/packages/block-editor/src/hooks/style.js
@@ -20,8 +20,7 @@ import { createHigherOrderComponent } from '@wordpress/compose';
import { BORDER_SUPPORT_KEY, BorderPanel } from './border';
import { COLOR_SUPPORT_KEY, ColorEdit } from './color';
import { TypographyPanel, TYPOGRAPHY_SUPPORT_KEYS } from './typography';
-import { SPACING_SUPPORT_KEY, PaddingEdit } from './padding';
-import SpacingPanelControl from '../components/spacing-panel-control';
+import { SPACING_SUPPORT_KEY, SpacingPanel } from './spacing';
const styleSupportKeys = [
...TYPOGRAPHY_SUPPORT_KEYS,
@@ -140,7 +139,7 @@ export function addSaveProps( props, blockType, attributes ) {
}
/**
- * Filters registered block settings to extand the block edit wrapper
+ * Filters registered block settings to extend the block edit wrapper
* to apply the desired styles and classnames properly.
*
* @param {Object} settings Original block settings
@@ -173,23 +172,12 @@ export function addEditProps( settings ) {
*/
export const withBlockControls = createHigherOrderComponent(
( BlockEdit ) => ( props ) => {
- const { name: blockName } = props;
-
- const hasSpacingSupport = hasBlockSupport(
- blockName,
- SPACING_SUPPORT_KEY
- );
-
return [
,
,
,
,
- hasSpacingSupport && (
-
-
-
- ),
+ ,
];
},
'withToolbarControls'
diff --git a/packages/block-editor/src/hooks/test/style.js b/packages/block-editor/src/hooks/test/style.js
index afa1d45856b2a..bb3880c163fdd 100644
--- a/packages/block-editor/src/hooks/test/style.js
+++ b/packages/block-editor/src/hooks/test/style.js
@@ -18,6 +18,9 @@ describe( 'getInlineStyles', () => {
color: { text: 'red', background: 'black' },
typography: { lineHeight: 1.5, fontSize: 10 },
border: { radius: 10 },
+ spacing: {
+ padding: { top: '10px' },
+ },
} )
).toEqual( {
backgroundColor: 'black',
@@ -25,6 +28,7 @@ describe( 'getInlineStyles', () => {
color: 'red',
lineHeight: 1.5,
fontSize: 10,
+ paddingTop: '10px',
} );
} );
} );
diff --git a/packages/edit-site/src/components/sidebar/spacing-panel.js b/packages/edit-site/src/components/sidebar/spacing-panel.js
index f2609b49c4696..a244491c6a4e1 100644
--- a/packages/edit-site/src/components/sidebar/spacing-panel.js
+++ b/packages/edit-site/src/components/sidebar/spacing-panel.js
@@ -6,13 +6,20 @@ import {
__experimentalBoxControl as BoxControl,
PanelBody,
} from '@wordpress/components';
+import { getBlockSupport } from '@wordpress/blocks';
/**
* Internal dependencies
*/
import { useEditorFeature } from '../editor/utils';
-export function useHasSpacingPanel( { supports, name } ) {
+export function useHasSpacingPanel( context ) {
+ const hasPadding = useHasPadding( context );
+
+ return hasPadding;
+}
+
+export function useHasPadding( { name, supports } ) {
return (
useEditorFeature( 'spacing.customPadding', name ) &&
supports.includes( 'padding' )
@@ -35,29 +42,58 @@ function useCustomUnits( { units, contextName } ) {
return usedUnits.length === 0 ? false : usedUnits;
}
-export default function SpacingPanel( {
- context: { name },
- getStyle,
- setStyle,
-} ) {
+function useCustomSides( blockName, feature ) {
+ const support = getBlockSupport( blockName, 'spacing' );
+
+ // Return empty config when setting is boolean as theme isn't setting
+ // arbitrary sides.
+ if ( typeof support[ feature ] === 'boolean' ) {
+ return {};
+ }
+
+ return support[ feature ];
+}
+
+function filterValuesBySides( values, sides ) {
+ if ( Object.entries( sides ).length === 0 ) {
+ // If no custom side configuration all sides are opted into by default.
+ return values;
+ }
+
+ // Only include sides opted into within filtered values.
+ return Object.keys( sides )
+ .filter( ( side ) => sides[ side ] )
+ .reduce(
+ ( filtered, side ) => ( { ...filtered, [ side ]: values[ side ] } ),
+ {}
+ );
+}
+
+export default function SpacingPanel( { context, getStyle, setStyle } ) {
+ const { name } = context;
+ const showPaddingControl = useHasPadding( context );
const units = useCustomUnits( { contextName: name } );
+
const paddingValues = getStyle( name, 'padding' );
- const setPaddingValues = ( { top, right, bottom, left } ) => {
- setStyle( name, 'padding', {
- top: top || paddingValues?.top,
- right: right || paddingValues?.right,
- bottom: bottom || paddingValues?.bottom,
- left: left || paddingValues?.left,
- } );
+ const paddingSides = useCustomSides( name, 'padding' );
+
+ const setPaddingValues = ( newPaddingValues ) => {
+ const padding = filterValuesBySides( newPaddingValues, paddingSides );
+ setStyle( name, 'padding', padding );
};
+
return (
-
+ { showPaddingControl && (
+
+ ) }
);
}