Skip to content

Commit

Permalink
Add style engine handling of spacing presets
Browse files Browse the repository at this point in the history
  • Loading branch information
Glen Davies committed Jul 1, 2022
1 parent 6eecad6 commit 64479cf
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 28 deletions.
2 changes: 1 addition & 1 deletion lib/block-supports/border.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {

// Collect classes and styles.
$attributes = array();
$styles = gutenberg_style_engine_generate( array( 'border' => $border_block_styles ) );
$styles = gutenberg_style_engine_generate( array( 'border' => $border_block_styles ), array( 'css_vars' => true ) );

if ( ! empty( $styles['classnames'] ) ) {
$attributes['class'] = $styles['classnames'];
Expand Down
3 changes: 2 additions & 1 deletion lib/block-supports/spacing.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) {
$spacing_block_styles['padding'] = $has_padding_support && ! $skip_padding ? _wp_array_get( $block_styles, array( 'spacing', 'padding' ), null ) : null;
$spacing_block_styles['margin'] = $has_margin_support && ! $skip_margin ? _wp_array_get( $block_styles, array( 'spacing', 'margin' ), null ) : null;
$styles = gutenberg_style_engine_generate(
array( 'spacing' => $spacing_block_styles )
array( 'spacing' => $spacing_block_styles ),
array( 'css_vars' => true )
);

if ( ! empty( $styles['css'] ) ) {
Expand Down
69 changes: 46 additions & 23 deletions packages/style-engine/class-wp-style-engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class WP_Style_Engine {
),
'path' => array( 'color', 'text' ),
'css_vars' => array(
'--wp--preset--color--$slug' => 'color',
'color' => '--wp--preset--color--$slug',
),
'classnames' => array(
'has-text-color' => true,
Expand Down Expand Up @@ -148,13 +148,19 @@ class WP_Style_Engine {
'individual' => 'padding-%s',
),
'path' => array( 'spacing', 'padding' ),
'css_vars' => array(
'spacing' => '--wp--preset--spacing--$slug',
),
),
'margin' => array(
'property_keys' => array(
'default' => 'margin',
'individual' => 'margin-%s',
),
'path' => array( 'spacing', 'margin' ),
'css_vars' => array(
'spacing' => '--wp--preset--spacing--$slug',
),
),
),
'typography' => array(
Expand Down Expand Up @@ -246,6 +252,28 @@ protected static function get_slug_from_preset_value( $style_value, $property_ke
return null;
}

/**
* Generates a css var string, eg var(--wp--preset--color--background) from a preset string, eg. `var:preset|space|50`.
*
* @param string $style_value A single css preset value.
* @param array $css_vars The css var patterns used to generate the var string.
*
* @return string|null The css var, or null if no match for slug found.
*/
protected static function get_css_var_value( $style_value, $css_vars ) {
foreach ( $css_vars as $property_key => $css_var_pattern ) {
$slug = static::get_slug_from_preset_value( $style_value, $property_key );
if ( $slug ) {
$var = strtr(
$css_var_pattern,
array( '$slug' => $slug )
);
return "var($var)";
}
}
return null;
}

/**
* Checks whether an incoming block style value is valid.
*
Expand Down Expand Up @@ -315,7 +343,7 @@ protected static function get_css_declarations( $style_value, $style_definition,
isset( $style_definition['value_func'] ) &&
is_callable( $style_definition['value_func'] )
) {
return call_user_func( $style_definition['value_func'], $style_value, $style_definition );
return call_user_func( $style_definition['value_func'], $style_value, $style_definition, $should_return_css_vars );
}

$css_declarations = array();
Expand All @@ -325,15 +353,9 @@ protected static function get_css_declarations( $style_value, $style_definition,
// Check if the value is a CSS preset and there's a corresponding css_var pattern in the style definition.
if ( is_string( $style_value ) && strpos( $style_value, 'var:' ) !== false ) {
if ( $should_return_css_vars && ! empty( $style_definition['css_vars'] ) ) {
foreach ( $style_definition['css_vars'] as $css_var_pattern => $property_key ) {
$slug = static::get_slug_from_preset_value( $style_value, $property_key );
if ( $slug ) {
$css_var = strtr(
$css_var_pattern,
array( '$slug' => $slug )
);
$css_declarations[ $style_property_keys['default'] ] = "var($css_var)";
}
$css_var = static::get_css_var_value( $style_value, $style_definition['css_vars'] );
if ( $css_var ) {
$css_declarations[ $style_property_keys['default'] ] = $css_var;
}
}
return $css_declarations;
Expand All @@ -344,8 +366,13 @@ protected static function get_css_declarations( $style_value, $style_definition,
// for styles such as margins and padding.
if ( is_array( $style_value ) ) {
foreach ( $style_value as $key => $value ) {
$individual_property = sprintf( $style_property_keys['individual'], _wp_to_kebab_case( $key ) );
$css_declarations[ $individual_property ] = $value;
if ( is_string( $value ) && strpos( $value, 'var:' ) !== false && $should_return_css_vars && ! empty( $style_definition['css_vars'] ) ) {
$value = static::get_css_var_value( $value, $style_definition['css_vars'] );
}
$individual_property = sprintf( $style_property_keys['individual'], _wp_to_kebab_case( $key ) );
if ( $value ) {
$css_declarations[ $individual_property ] = $value;
}
}
} else {
$css_declarations[ $style_property_keys['default'] ] = $style_value;
Expand Down Expand Up @@ -441,12 +468,13 @@ public function generate( $block_styles, $options ) {
* "border-{top|right|bottom|left}-{color|width|style}: {value};" or,
* "border-image-{outset|source|width|repeat|slice}: {value};"
*
* @param array $style_value A single raw Gutenberg style attributes value for a CSS property.
* @param array $individual_property_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA.
* @param array $style_value A single raw Gutenberg style attributes value for a CSS property.
* @param array $individual_property_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA.
* @param boolean $should_return_css_vars Whether to try to build and return CSS var values.
*
* @return array An array of CSS definitions, e.g., array( "$property" => "$value" ).
*/
protected static function get_individual_property_css_declarations( $style_value, $individual_property_definition ) {
protected static function get_individual_property_css_declarations( $style_value, $individual_property_definition, $should_return_css_vars ) {
$css_declarations = array();

if ( ! is_array( $style_value ) || empty( $style_value ) || empty( $individual_property_definition['path'] ) ) {
Expand All @@ -470,13 +498,8 @@ protected static function get_individual_property_css_declarations( $style_value

if ( $style_definition && isset( $style_definition['property_keys']['individual'] ) ) {
// Set a CSS var if there is a valid preset value.
$slug = isset( $individual_property_definition['css_vars'][ $css_property ] ) ? static::get_slug_from_preset_value( $value, $css_property ) : null;
if ( $slug ) {
$css_var = strtr(
$individual_property_definition['css_vars'][ $css_property ],
array( '$slug' => $slug )
);
$value = "var($css_var)";
if ( is_string( $value ) && strpos( $value, 'var:' ) !== false && $should_return_css_vars && ! empty( $individual_property_definition['css_vars'] ) ) {
$value = static::get_css_var_value( $value, $individual_property_definition['css_vars'] );
}
$individual_css_property = sprintf( $style_definition['property_keys']['individual'], $individual_property_key );
$css_declarations[ $individual_css_property ] = $value;
Expand Down
57 changes: 55 additions & 2 deletions packages/style-engine/phpunit/class-wp-style-engine-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,59 @@ public function data_generate_styles_fixtures() {
),
),

'valid_spacing_single_preset_values' => array(
'block_styles' => array(
'spacing' => array(
'margin' => 'var:preset|spacing|10',
'padding' => 'var:preset|spacing|20',
),
),
'options' => array( 'css_vars' => true ),
'expected_output' => array(
'css' => 'padding: var(--wp--preset--spacing--20); margin: var(--wp--preset--spacing--10);',
),
),

'valid_spacing_multi_preset_values' => array(
'block_styles' => array(
'spacing' => array(
'margin' => array(
'left' => 'var:preset|spacing|10',
'right' => 'var:preset|spacing|20',
'top' => '1rem',
'bottom' => '1rem',
),
'padding' => array(
'left' => 'var:preset|spacing|30',
'right' => 'var:preset|spacing|40',
'top' => '14px',
'bottom' => '14px',
),
),
),
'options' => array( 'css_vars' => true ),
'expected_output' => array(
'css' => 'padding-left: var(--wp--preset--spacing--30); padding-right: var(--wp--preset--spacing--40); padding-top: 14px; padding-bottom: 14px; margin-left: var(--wp--preset--spacing--10); margin-right: var(--wp--preset--spacing--20); margin-top: 1rem; margin-bottom: 1rem;',
),
),

'invalid_spacing_multi_preset_values' => array(
'block_styles' => array(
'spacing' => array(
'margin' => array(
'left' => 'var:preset|spaceman|10',
'right' => 'var:preset|spaceman|20',
'top' => '1rem',
'bottom' => '1rem',
),
),
),
'options' => array( 'css_vars' => true ),
'expected_output' => array(
'css' => 'margin-top: 1rem; margin-bottom: 1rem;',
),
),

'invalid_classnames_options' => array(
'block_styles' => array(
'typography' => array(
Expand Down Expand Up @@ -285,7 +338,7 @@ public function data_generate_styles_fixtures() {
),
),
),
'options' => array(),
'options' => array( 'css_vars' => true ),
'expected_output' => array(
'css' => 'border-top-color: #fe1; border-top-width: 1.5rem; border-top-style: dashed; border-right-color: #fe2; border-right-width: 1.4rem; border-right-style: solid; border-bottom-color: #fe3; border-bottom-width: 1.3rem; border-left-color: var(--wp--preset--color--swampy-yellow); border-left-width: 0.5rem; border-left-style: dotted;',
),
Expand Down Expand Up @@ -315,7 +368,7 @@ public function data_generate_styles_fixtures() {
),
),
),
'options' => array(),
'options' => array( 'css_vars' => true ),
'expected_output' => array(
'css' => 'border-bottom-color: var(--wp--preset--color--terrible-lizard);',
),
Expand Down
4 changes: 3 additions & 1 deletion packages/style-engine/src/styles/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ export function generateBoxRules(
} else {
const sideRules = individualProperties.reduce(
( acc: GeneratedCSSRule[], side: string ) => {
const value: string | undefined = get( boxStyle, [ side ] );
const value: string | undefined = getCSSVarFromStyleValue(
get( boxStyle, [ side ] )
);
if ( value ) {
acc.push( {
selector: options?.selector,
Expand Down

0 comments on commit 64479cf

Please sign in to comment.