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

Spacing Support: Add margin block support with configurable sides #30608

Merged
merged 3 commits into from
May 11, 2021
Merged
Show file tree
Hide file tree
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
7 changes: 7 additions & 0 deletions docs/how-to-guides/themes/theme-json.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ The settings section has the following structure and default values:
"wideSize": "1000px",
},
"spacing": {
"customMargin": false,
"customPadding": false, /* Supersedes add_theme_support('custom-spacing') */
"units": [ "px", "em", "rem", "vh", "vw" ], /* filter values, as in add_theme_support('custom-units', ... ) */
},
Expand Down Expand Up @@ -464,6 +465,12 @@ Each block declares which style properties it exposes via the [block supports me
"text": "value"
},
"spacing": {
"margin": {
"top": "value",
"right": "value",
"bottom": "value",
"left": "value"
},
"padding": {
"top": "value",
"right": "value",
Expand Down
7 changes: 5 additions & 2 deletions docs/reference-guides/block-api/block-supports.md
Original file line number Diff line number Diff line change
Expand Up @@ -497,26 +497,29 @@ supports: {
- Type: `Object`
- Default value: null
- Subproperties:
- `margin`: type `boolean` or `array`, default value `false`
- `padding`: type `boolean` or `array`, default value `false`

This value signals that a block supports some of the CSS style properties related to spacing. When it does, the block editor will show UI controls for the user to set their values, if [the theme declares support](/docs/how-to-guides/themes/theme-support.md#cover-block-padding).

```js
supports: {
spacing: {
margin: true, // Enable margin UI control.
padding: true, // Enable padding UI control.
}
}
```

When the block declares support for a specific spacing property, the attributes definition is extended to include the `style` attribute.

- `style`: attribute of `object` type with no default assigned. This is added when `padding` support is declared. It stores the custom values set by the user.
- `style`: attribute of `object` type with no default assigned. This is added when `margin` or `padding` support is declared. It stores the custom values set by the user.

```js
supports: {
spacing: {
padding: [ 'top', 'bottom' ], // Enable padding for arbitrary sides.
margin: [ 'top', 'bottom' ], // Enable margin for arbitrary sides.
padding: true, // Enable padding for all sides.
}
}
```
Expand Down
4 changes: 2 additions & 2 deletions lib/block-supports/layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
?>
<?php echo '.wp-container-' . $id; ?> > * {
<?php echo esc_html( safecss_filter_attr( $all_max_width_declaration ) ); ?>;
margin-left: auto;
margin-right: auto;
margin-left: auto !important;
margin-right: auto !important;
}

<?php echo '.wp-container-' . $id; ?> > .alignwide {
Expand Down
11 changes: 11 additions & 0 deletions lib/class-wp-theme-json.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ class WP_Theme_JSON {
'text' => null,
),
'spacing' => array(
'margin' => array(
'top' => null,
'right' => null,
'bottom' => null,
'left' => null,
),
'padding' => array(
'bottom' => null,
'left' => null,
Expand Down Expand Up @@ -91,6 +97,7 @@ class WP_Theme_JSON {
'custom' => null,
'layout' => null,
'spacing' => array(
'customMargin' => null,
'customPadding' => null,
'units' => null,
),
Expand Down Expand Up @@ -237,6 +244,10 @@ class WP_Theme_JSON {
'line-height' => array(
'value' => array( 'typography', 'lineHeight' ),
),
'margin' => array(
'value' => array( 'spacing', 'margin' ),
'properties' => array( 'top', 'right', 'bottom', 'left' ),
),
'padding' => array(
'value' => array( 'spacing', 'padding' ),
'properties' => array( 'top', 'right', 'bottom', 'left' ),
Expand Down
1 change: 1 addition & 0 deletions lib/experimental-default-theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@
]
},
"spacing": {
"customMargin": false,
"customPadding": false,
"units": [ "px", "em", "rem", "vh", "vw" ]
},
Expand Down
4 changes: 2 additions & 2 deletions packages/block-editor/src/components/block-list/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ export function LayoutStyle( { selector, layout = {} } ) {
? `
${ appendSelectors( selector, '> *' ) } {
max-width: ${ contentSize ?? wideSize };
margin-left: auto;
margin-right: auto;
margin-left: auto !important;
margin-right: auto !important;
}

${ appendSelectors( selector, '> [data-align="wide"]' ) } {
Expand Down
101 changes: 101 additions & 0 deletions packages/block-editor/src/hooks/margin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Platform } from '@wordpress/element';
import { getBlockSupport } from '@wordpress/blocks';
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';

/**
* Determines if there is margin support.
*
* @param {string|Object} blockType Block name or Block Type object.
* @return {boolean} Whether there is support.
*/
export function hasMarginSupport( blockType ) {
const support = getBlockSupport( blockType, SPACING_SUPPORT_KEY );
return !! ( true === support || support?.margin );
}

/**
* Custom hook that checks if margin settings have been disabled.
*
* @param {string} name The name of the block.
* @return {boolean} Whether margin setting is disabled.
*/
export function useIsMarginDisabled( { name: blockName } = {} ) {
const isDisabled = ! useEditorFeature( 'spacing.customMargin' );
return ! hasMarginSupport( blockName ) || isDisabled;
}

/**
* Inspector control panel containing the margin related configuration
*
* @param {Object} props Block props.
* @return {WPElement} Margin edit element.
*/
export function MarginEdit( props ) {
const {
name: blockName,
attributes: { style },
setAttributes,
} = props;

const units = useCustomUnits();
const sides = useCustomSides( blockName, 'margin' );

if ( ! hasMarginSupport( blockName ) ) {
return null;
}

const onChange = ( next ) => {
const newStyle = {
...style,
spacing: {
...style?.spacing,
margin: next,
},
};

setAttributes( {
style: cleanEmptyObject( newStyle ),
} );
};

const onChangeShowVisualizer = ( next ) => {
const newStyle = {
...style,
visualizers: {
margin: next,
},
};

setAttributes( {
style: cleanEmptyObject( newStyle ),
} );
};

return Platform.select( {
web: (
<>
<BoxControl
values={ style?.spacing?.margin }
onChange={ onChange }
onChangeShowVisualizer={ onChangeShowVisualizer }
label={ __( 'Margin' ) }
sides={ sides }
units={ units }
/>
</>
),
native: null,
} );
}
9 changes: 6 additions & 3 deletions packages/block-editor/src/hooks/spacing.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getBlockSupport } from '@wordpress/blocks';
* Internal dependencies
*/
import InspectorControls from '../components/inspector-controls';
import { MarginEdit, hasMarginSupport, useIsMarginDisabled } from './margin';
import {
PaddingEdit,
hasPaddingSupport,
Expand All @@ -36,13 +37,14 @@ export function SpacingPanel( props ) {
<InspectorControls key="spacing">
<PanelBody title={ __( 'Spacing' ) }>
<PaddingEdit { ...props } />
<MarginEdit { ...props } />
</PanelBody>
</InspectorControls>
);
}

/**
* Determine whether there is block support for padding.
* Determine whether there is block support for padding or margins.
*
* @param {string} blockName Block name.
* @return {boolean} Whether there is support.
Expand All @@ -52,7 +54,7 @@ export function hasSpacingSupport( blockName ) {
return false;
}

return hasPaddingSupport( blockName );
return hasPaddingSupport( blockName ) || hasMarginSupport( blockName );
}

/**
Expand All @@ -63,8 +65,9 @@ export function hasSpacingSupport( blockName ) {
*/
const useIsSpacingDisabled = ( props = {} ) => {
const paddingDisabled = useIsPaddingDisabled( props );
const marginDisabled = useIsMarginDisabled( props );

return paddingDisabled;
return paddingDisabled && marginDisabled;
};

/**
Expand Down
2 changes: 2 additions & 0 deletions packages/block-editor/src/hooks/test/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe( 'getInlineStyles', () => {
},
spacing: {
padding: { top: '10px' },
margin: { bottom: '15px' },
},
} )
).toEqual( {
Expand All @@ -36,6 +37,7 @@ describe( 'getInlineStyles', () => {
color: 'red',
lineHeight: 1.5,
fontSize: 10,
marginBottom: '15px',
paddingTop: '10px',
} );
} );
Expand Down
5 changes: 5 additions & 0 deletions packages/blocks/src/api/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = {
value: [ 'typography', 'lineHeight' ],
support: [ 'lineHeight' ],
},
margin: {
value: [ 'spacing', 'margin' ],
support: [ 'spacing', 'margin' ],
properties: [ 'top', 'right', 'bottom', 'left' ],
},
padding: {
value: [ 'spacing', 'padding' ],
support: [ 'spacing', 'padding' ],
Expand Down
36 changes: 30 additions & 6 deletions packages/edit-site/src/components/sidebar/spacing-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,21 @@ const CSS_UNITS = [

export function useHasSpacingPanel( context ) {
const hasPadding = useHasPadding( context );
const hasMargin = useHasMargin( context );

return hasPadding;
return hasPadding || hasMargin;
}

export function useHasPadding( { name, supports } ) {
return (
useEditorFeature( 'spacing.customPadding', name ) &&
supports.includes( 'padding' )
);
function useHasPadding( { name, supports } ) {
const settings = useEditorFeature( 'spacing.customPadding', name );

return settings && supports.includes( 'padding' );
}

function useHasMargin( { name, supports } ) {
const settings = useEditorFeature( 'spacing.customMargin', name );

return settings && supports.includes( 'margin' );
}

function filterUnitsWithSettings( settings = [], units = [] ) {
Expand Down Expand Up @@ -88,6 +94,7 @@ function filterValuesBySides( values, sides ) {
export default function SpacingPanel( { context, getStyle, setStyle } ) {
const { name } = context;
const showPaddingControl = useHasPadding( context );
const showMarginControl = useHasMargin( context );
const units = useCustomUnits( { contextName: name, units: CSS_UNITS } );

const paddingValues = getStyle( name, 'padding' );
Expand All @@ -98,6 +105,14 @@ export default function SpacingPanel( { context, getStyle, setStyle } ) {
setStyle( name, 'padding', padding );
};

const marginValues = getStyle( name, 'margin' );
const marginSides = useCustomSides( name, 'margin' );

const setMarginValues = ( newMarginValues ) => {
const margin = filterValuesBySides( newMarginValues, marginSides );
setStyle( name, 'margin', margin );
};

return (
<PanelBody title={ __( 'Spacing' ) }>
{ showPaddingControl && (
Expand All @@ -109,6 +124,15 @@ export default function SpacingPanel( { context, getStyle, setStyle } ) {
units={ units }
/>
) }
{ showMarginControl && (
<BoxControl
values={ marginValues }
onChange={ setMarginValues }
label={ __( 'Margin' ) }
sides={ marginSides }
units={ units }
/>
) }
</PanelBody>
);
}