Skip to content

Commit

Permalink
BlockGap: Add support for spacing presets (#43296)
Browse files Browse the repository at this point in the history
* BlockGap: Add support for spacing presets

* Add JS implementation

* Fix output for root CSS variable

* Add JS tests

* Add PHP test

* For consistency, use 0.5em fallback gap in sides that don't have a gap entered, in flex layout
  • Loading branch information
andrewserong authored Aug 18, 2022
1 parent 45e0fe2 commit c76c87e
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 15 deletions.
27 changes: 22 additions & 5 deletions lib/block-supports/layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
$gap_value = isset( $gap_value['top'] ) ? $gap_value['top'] : null;
}
if ( $gap_value && ! $should_skip_gap_serialization ) {
// Get spacing CSS variable from preset value if provided.
if ( is_string( $gap_value ) && strpos( $gap_value, 'var:preset|spacing|' ) !== false ) {
$index_to_splice = strrpos( $gap_value, '|' ) + 1;
$slug = _wp_to_kebab_case( substr( $gap_value, $index_to_splice ) );
$gap_value = "var(--wp--preset--spacing--$slug)";
}

array_push(
$layout_styles,
array(
Expand Down Expand Up @@ -150,12 +157,22 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
);
}

if ( $has_block_gap_support ) {
if ( is_array( $gap_value ) ) {
$gap_row = isset( $gap_value['top'] ) ? $gap_value['top'] : $fallback_gap_value;
$gap_column = isset( $gap_value['left'] ) ? $gap_value['left'] : $fallback_gap_value;
$gap_value = $gap_row === $gap_column ? $gap_row : $gap_row . ' ' . $gap_column;
if ( $has_block_gap_support && isset( $gap_value ) ) {
$combined_gap_value = '';
$gap_sides = is_array( $gap_value ) ? array( 'top', 'left' ) : array( 'top' );

foreach ( $gap_sides as $gap_side ) {
$process_value = is_string( $gap_value ) ? $gap_value : _wp_array_get( $gap_value, array( $gap_side ), $fallback_gap_value );
// Get spacing CSS variable from preset value if provided.
if ( is_string( $process_value ) && strpos( $process_value, 'var:preset|spacing|' ) !== false ) {
$index_to_splice = strrpos( $process_value, '|' ) + 1;
$slug = _wp_to_kebab_case( substr( $process_value, $index_to_splice ) );
$process_value = "var(--wp--preset--spacing--$slug)";
}
$combined_gap_value .= "$process_value ";
}
$gap_value = trim( $combined_gap_value );

if ( $gap_value && ! $should_skip_gap_serialization ) {
$layout_styles[] = array(
'selector' => $selector,
Expand Down
14 changes: 7 additions & 7 deletions lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php
Original file line number Diff line number Diff line change
Expand Up @@ -793,8 +793,6 @@ function( $pseudo_selector ) use ( $selector ) {
}

if ( static::ROOT_BLOCK_SELECTOR === $selector ) {
$block_gap_value = _wp_array_get( $this->theme_json, array( 'styles', 'spacing', 'blockGap' ), '0.5em' );

if ( $use_root_padding ) {
$block_rules .= '.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }';
$block_rules .= '.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }';
Expand All @@ -808,8 +806,10 @@ function( $pseudo_selector ) use ( $selector ) {

$has_block_gap_support = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'blockGap' ) ) !== null;
if ( $has_block_gap_support ) {
$block_rules .= '.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }';
$block_rules .= ".wp-site-blocks > * + * { margin-block-start: $block_gap_value; }";
$block_gap_value = static::get_property_value( $this->theme_json, array( 'styles', 'spacing', 'blockGap' ) );
$block_rules .= '.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }';
$block_rules .= ".wp-site-blocks > * + * { margin-block-start: $block_gap_value; }";

// For backwards compatibility, ensure the legacy block gap CSS variable is still available.
$block_rules .= "$selector { --wp--style--block-gap: $block_gap_value; }";
}
Expand Down Expand Up @@ -1308,14 +1308,14 @@ protected function get_layout_styles( $block_metadata ) {
$block_gap_value = _wp_array_get( $block_type->supports, array( 'spacing', 'blockGap', '__experimentalDefault' ), null );
}
} else {
$block_gap_value = _wp_array_get( $node, array( 'spacing', 'blockGap' ), null );
$block_gap_value = static::get_property_value( $node, array( 'spacing', 'blockGap' ) );
}

// Support split row / column values and concatenate to a shorthand value.
if ( is_array( $block_gap_value ) ) {
if ( isset( $block_gap_value['top'] ) && isset( $block_gap_value['left'] ) ) {
$gap_row = $block_gap_value['top'];
$gap_column = $block_gap_value['left'];
$gap_row = static::get_property_value( $node, array( 'spacing', 'blockGap', 'top' ) );
$gap_column = static::get_property_value( $node, array( 'spacing', 'blockGap', 'left' ) );
$block_gap_value = $gap_row === $gap_column ? $gap_row : $gap_row . ' ' . $gap_column;
} else {
// Skip outputting gap value if not all sides are provided.
Expand Down
9 changes: 7 additions & 2 deletions packages/block-editor/src/hooks/gap.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
* Internal dependencies
*/
import { __unstableUseBlockRef as useBlockRef } from '../components/block-list/use-block-props/use-block-refs';
import { getSpacingPresetCssVar } from '../components/spacing-sizes-control/utils';
import useSetting from '../components/use-setting';
import { AXIAL_SIDES, SPACING_SUPPORT_KEY, useCustomSides } from './dimensions';
import { cleanEmptyObject } from './utils';
Expand Down Expand Up @@ -54,8 +55,12 @@ export function getGapBoxControlValueFromStyle( blockGapValue ) {

const isValueString = typeof blockGapValue === 'string';
return {
top: isValueString ? blockGapValue : blockGapValue?.top,
left: isValueString ? blockGapValue : blockGapValue?.left,
top: isValueString
? getSpacingPresetCssVar( blockGapValue )
: getSpacingPresetCssVar( blockGapValue?.top ),
left: isValueString
? getSpacingPresetCssVar( blockGapValue )
: getSpacingPresetCssVar( blockGapValue?.left ),
};
}

Expand Down
22 changes: 22 additions & 0 deletions packages/block-editor/src/hooks/test/gap.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,28 @@ describe( 'gap', () => {
...blockGapValue,
} );
} );
it( 'should unwrap var: values from a string into a CSS var() function', () => {
const expectedValue = {
top: 'var(--wp--preset--spacing--60)',
left: 'var(--wp--preset--spacing--60)',
};
expect(
getGapBoxControlValueFromStyle( 'var:preset|spacing|60' )
).toEqual( expectedValue );
} );
it( 'should unwrap var: values from an object into a CSS var() function', () => {
const expectedValue = {
top: 'var(--wp--preset--spacing--20)',
left: 'var(--wp--preset--spacing--60)',
};
const blockGapValue = {
top: 'var:preset|spacing|20',
left: 'var:preset|spacing|60',
};
expect( getGapBoxControlValueFromStyle( blockGapValue ) ).toEqual(
expectedValue
);
} );
} );
describe( 'getGapCSSValue()', () => {
it( 'should return `null` if argument is falsey', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/block-editor/src/layouts/flex.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export default {
const blockGapValue =
style?.spacing?.blockGap &&
! shouldSkipSerialization( blockName, 'spacing', 'blockGap' )
? getGapCSSValue( style?.spacing?.blockGap )
? getGapCSSValue( style?.spacing?.blockGap, '0.5em' )
: undefined;
const justifyContent = justifyContentMap[ layout.justifyContent ];
const flexWrap = flexWrapOptions.includes( layout.flexWrap )
Expand Down
33 changes: 33 additions & 0 deletions phpunit/class-wp-theme-json-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,39 @@ public function test_get_stylesheet_generates_layout_styles( $layout_definitions
);
}

/**
* @dataProvider data_get_layout_definitions
*
* @param array $layout_definitions Layout definitions as stored in core theme.json.
*/
public function test_get_stylesheet_generates_layout_styles_with_spacing_presets( $layout_definitions ) {
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'settings' => array(
'layout' => array(
'definitions' => $layout_definitions,
),
'spacing' => array(
'blockGap' => true,
),
),
'styles' => array(
'spacing' => array(
'blockGap' => 'var:preset|spacing|60',
),
),
),
'default'
);

// Results also include root site blocks styles.
$this->assertEquals(
'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var(--wp--preset--spacing--60); }body { --wp--style--block-gap: var(--wp--preset--spacing--60); }body .is-layout-flow > *{margin-block-start: 0;margin-block-end: 0;}body .is-layout-flow > * + *{margin-block-start: var(--wp--preset--spacing--60);margin-block-end: 0;}body .is-layout-flex{gap: var(--wp--preset--spacing--60);}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}',
$theme_json->get_stylesheet( array( 'styles' ) )
);
}

/**
* @dataProvider data_get_layout_definitions
*
Expand Down

0 comments on commit c76c87e

Please sign in to comment.