From 3cc88f3628756288ba5da0b9e1c4ee63db64c092 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 15 Aug 2023 15:38:10 +1000 Subject: [PATCH 1/5] Design Tools: Add block instance element styling for headings --- lib/block-supports/colors.php | 4 +- lib/block-supports/elements.php | 121 +++++++++++++----- packages/block-editor/src/hooks/style.js | 60 ++++++++- packages/block-editor/src/hooks/utils.js | 2 + .../style-engine/class-wp-style-engine.php | 6 + 5 files changed, 159 insertions(+), 34 deletions(-) diff --git a/lib/block-supports/colors.php b/lib/block-supports/colors.php index 7ec32bf14d7537..53213df34d9ffb 100644 --- a/lib/block-supports/colors.php +++ b/lib/block-supports/colors.php @@ -16,10 +16,12 @@ function gutenberg_register_colors_support( $block_type ) { $has_background_colors_support = true === $color_support || ( is_array( $color_support ) && _wp_array_get( $color_support, array( 'background' ), true ) ); $has_gradients_support = _wp_array_get( $color_support, array( 'gradients' ), false ); $has_link_colors_support = _wp_array_get( $color_support, array( 'link' ), false ); + $has_heading_colors_support = _wp_array_get( $color_support, array( 'heading' ), false ); $has_color_support = $has_text_colors_support || $has_background_colors_support || $has_gradients_support || - $has_link_colors_support; + $has_link_colors_support || + $has_heading_colors_support; if ( ! $block_type->attributes ) { $block_type->attributes = array(); diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php index d4502aaa2e4785..1e7f8aeda07be3 100644 --- a/lib/block-supports/elements.php +++ b/lib/block-supports/elements.php @@ -23,34 +23,66 @@ function gutenberg_get_elements_class_name( $block ) { * @return string Filtered block content. */ function gutenberg_render_elements_support( $block_content, $block ) { - if ( ! $block_content ) { + if ( ! $block_content || empty( $block['attrs'] ) ) { return $block_content; } $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); $skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ); + $skip_heading_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ); - if ( $skip_link_color_serialization ) { + if ( $skip_link_color_serialization && $skip_heading_color_serialization ) { return $block_content; } - $link_color = null; - if ( ! empty( $block['attrs'] ) ) { - $link_color = _wp_array_get( $block['attrs'], array( 'style', 'elements', 'link', 'color', 'text' ), null ); + $element_colors_set = 0; + + $link_color_paths = array( + 'style.elements.link.color.text', + 'style.elements.link.:hover.color.text', + ); + + foreach ( $link_color_paths as $element_color_path ) { + $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path, ), null ); + + if ( null !== $element_color && ! $skip_link_color_serialization ) { + $element_colors_set++; + } } - $hover_link_color = null; - if ( ! empty( $block['attrs'] ) ) { - $hover_link_color = _wp_array_get( $block['attrs'], array( 'style', 'elements', 'link', ':hover', 'color', 'text' ), null ); + $heading_color_paths = array( + 'style.elements.heading.color.text', + 'style.elements.heading.color.background', + 'style.elements.heading.color.gradient', + 'style.elements.h1.color.text', + 'style.elements.h1.color.background', + 'style.elements.h1.color.gradient', + 'style.elements.h2.color.text', + 'style.elements.h2.color.background', + 'style.elements.h2.color.gradient', + 'style.elements.h3.color.text', + 'style.elements.h3.color.background', + 'style.elements.h3.color.gradient', + 'style.elements.h4.color.text', + 'style.elements.h4.color.background', + 'style.elements.h4.color.gradient', + 'style.elements.h5.color.text', + 'style.elements.h5.color.background', + 'style.elements.h5.color.gradient', + 'style.elements.h6.color.text', + 'style.elements.h6.color.background', + 'style.elements.h6.color.gradient', + ); + + foreach ( $heading_color_paths as $element_color_path ) { + $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path, ), null ); + + if ( null !== $element_color && $skip_heading_color_serialization ) { + $element_colors_set++; + } } - /* - * For now we only care about link colors. - * This code in the future when we have a public API - * should take advantage of WP_Theme_JSON_Gutenberg::compute_style_properties - * and work for any element and style. - */ - if ( null === $link_color && null === $hover_link_color ) { + if ( ! $element_colors_set ) { return $block_content; } @@ -80,33 +112,62 @@ function gutenberg_render_elements_support_styles( $pre_render, $block ) { $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); $element_block_styles = isset( $block['attrs']['style']['elements'] ) ? $block['attrs']['style']['elements'] : null; - /* - * For now we only care about link color. - */ + if ( ! $element_block_styles ) { + return null; + } + $skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ); + $skip_heading_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ); - if ( $skip_link_color_serialization ) { + if ( $skip_link_color_serialization && $skip_heading_color_serialization ) { return null; } + $class_name = gutenberg_get_elements_class_name( $block ); - $link_block_styles = isset( $element_block_styles['link'] ) ? $element_block_styles['link'] : null; - gutenberg_style_engine_get_styles( - $link_block_styles, - array( - 'selector' => ".$class_name a", - 'context' => 'block-supports', - ) - ); + // Link colors + $link_block_styles = isset( $element_block_styles['link'] ) ? $element_block_styles['link'] : null; - if ( isset( $link_block_styles[':hover'] ) ) { + if ( ! $skip_link_color_serialization && $link_block_styles ) { gutenberg_style_engine_get_styles( - $link_block_styles[':hover'], + $link_block_styles, array( - 'selector' => ".$class_name a:hover", + 'selector' => ".$class_name a", 'context' => 'block-supports', ) ); + + if ( isset( $link_block_styles[':hover'] ) ) { + gutenberg_style_engine_get_styles( + $link_block_styles[':hover'], + array( + 'selector' => ".$class_name a:hover", + 'context' => 'block-supports', + ) + ); + } + } + + // Heading colors + if ( ! $skip_heading_color_serialization ) { + $heading_levels = array( 'heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ); + + foreach ( $heading_levels as $heading_level ) { + $heading_block_styles = isset( $element_block_styles[ $heading_level ] ) ? $element_block_styles[ $heading_level ] : null; + $heading_selector = 'heading' !== $heading_level + ? ".$class_name $heading_level" + : ".$class_name h1, .$class_name h2, .$class_name h3, .$class_name h4, .$class_name h5, .$class_name h6"; + + if ( $heading_block_styles ) { + gutenberg_style_engine_get_styles( + $heading_block_styles, + array( + 'selector' => $heading_selector, + 'context' => 'block-supports', + ) + ); + } + } } return null; diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index b416c86405e512..e973186a975717 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -34,6 +34,7 @@ import { } from './dimensions'; import useDisplayBlockControls from '../components/use-display-block-controls'; import { shouldSkipSerialization } from './utils'; +import { scopeSelector } from '../components/global-styles/utils'; import { useBlockEditingMode } from '../components/block-editing-mode'; const styleSupportKeys = [ @@ -382,6 +383,7 @@ const withElementsStyles = createHigherOrderComponent( const blockElementsContainerIdentifier = `wp-elements-${ useInstanceId( BlockListBlock ) }`; + const baseElementSelector = `.editor-styles-wrapper .${ blockElementsContainerIdentifier }`; const skipLinkColorSerialization = shouldSkipSerialization( props.name, @@ -389,6 +391,12 @@ const withElementsStyles = createHigherOrderComponent( 'link' ); + const skipHeadingColorSerialization = shouldSkipSerialization( + props.name, + COLOR_SUPPORT_KEY, + 'heading' + ); + const styles = useMemo( () => { // The .editor-styles-wrapper selector is required on elements styles. As it is // added to all other editor styles, not providing it causes reset and global @@ -398,14 +406,60 @@ const withElementsStyles = createHigherOrderComponent( styles: ! skipLinkColorSerialization ? props.attributes.style?.elements?.link : undefined, - selector: `.editor-styles-wrapper .${ blockElementsContainerIdentifier } ${ ELEMENTS.link }`, + selector: `${ baseElementSelector } ${ ELEMENTS.link }`, }, { styles: ! skipLinkColorSerialization ? props.attributes.style?.elements?.link?.[ ':hover' ] : undefined, - selector: `.editor-styles-wrapper .${ blockElementsContainerIdentifier } ${ ELEMENTS.link }:hover`, + selector: `${ baseElementSelector } ${ ELEMENTS.link }:hover`, + }, + { + styles: ! skipHeadingColorSerialization + ? props.attributes.style?.elements?.heading + : undefined, + selector: scopeSelector( + baseElementSelector, + ELEMENTS.heading + ), + }, + { + styles: ! skipHeadingColorSerialization + ? props.attributes.style?.elements?.h1 + : undefined, + selector: scopeSelector( baseElementSelector, ELEMENTS.h1 ), + }, + { + styles: ! skipHeadingColorSerialization + ? props.attributes.style?.elements?.h2 + : undefined, + selector: scopeSelector( baseElementSelector, ELEMENTS.h2 ), + }, + { + styles: ! skipHeadingColorSerialization + ? props.attributes.style?.elements?.h3 + : undefined, + selector: scopeSelector( baseElementSelector, ELEMENTS.h3 ), + }, + { + styles: ! skipHeadingColorSerialization + ? props.attributes.style?.elements?.h4 + : undefined, + selector: scopeSelector( baseElementSelector, ELEMENTS.h4 ), + }, + { + styles: ! skipHeadingColorSerialization + ? props.attributes.style?.elements?.h5 + : undefined, + selector: scopeSelector( baseElementSelector, ELEMENTS.h5 ), + }, + { + styles: ! skipHeadingColorSerialization + ? props.attributes.style?.elements?.h6 + : undefined, + selector: scopeSelector( baseElementSelector, ELEMENTS.h6 ), }, + //TODO: Refactor this to a helper that can more concisely flesh out the rest of the heading elements. ]; const elementCssRules = []; for ( const { styles: elementStyles, selector } of elements ) { @@ -421,7 +475,7 @@ const withElementsStyles = createHigherOrderComponent( : undefined; }, [ props.attributes.style?.elements, - blockElementsContainerIdentifier, + baseElementSelector, skipLinkColorSerialization, ] ); diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index 9c6bf957d61c51..a85c79a6e5277e 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -166,6 +166,7 @@ export function useBlockSettings( name, parentLayout ) { const isBackgroundEnabled = useSetting( 'color.background' ); const isLinkEnabled = useSetting( 'color.link' ); const isTextEnabled = useSetting( 'color.text' ); + const isHeadingEnabled = useSetting( 'color.heading' ); const rawSettings = useMemo( () => { return { @@ -193,6 +194,7 @@ export function useBlockSettings( name, parentLayout ) { customDuotone, background: isBackgroundEnabled, link: isLinkEnabled, + heading: isHeadingEnabled, text: isTextEnabled, }, typography: { diff --git a/packages/style-engine/class-wp-style-engine.php b/packages/style-engine/class-wp-style-engine.php index ec66168bc1a9a6..52cb3515c342e5 100644 --- a/packages/style-engine/class-wp-style-engine.php +++ b/packages/style-engine/class-wp-style-engine.php @@ -58,6 +58,9 @@ final class WP_Style_Engine { 'default' => 'background-color', ), 'path' => array( 'color', 'background' ), + 'css_vars' => array( + 'color' => '--wp--preset--color--$slug', + ), 'classnames' => array( 'has-background' => true, 'has-$slug-background-color' => 'color', @@ -67,6 +70,9 @@ final class WP_Style_Engine { 'property_keys' => array( 'default' => 'background', ), + 'css_vars' => array( + 'gradient' => '--wp--preset--gradient--$slug', + ), 'path' => array( 'color', 'gradient' ), 'classnames' => array( 'has-background' => true, From 7d3afdf5f02849cef333f35fd11e3b7440b18be1 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 15 Aug 2023 18:16:44 +1000 Subject: [PATCH 2/5] Add button element styling to block instances --- docs/reference-guides/core-blocks.md | 2 +- lib/block-supports/colors.php | 2 + lib/block-supports/elements.php | 55 +++++++++++++++++---- packages/block-editor/src/hooks/style.js | 15 ++++++ packages/block-editor/src/hooks/utils.js | 2 + packages/block-library/src/group/block.json | 1 + 6 files changed, 66 insertions(+), 11 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index e520166fa4bb34..267089cdb6d195 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -302,7 +302,7 @@ Gather blocks in a layout container. ([Source](https://github.com/WordPress/gute - **Name:** core/group - **Category:** design -- **Supports:** align (full, wide), anchor, ariaLabel, color (background, gradients, heading, link, text), dimensions (minHeight), layout (allowSizingOnChildren), position (sticky), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~ +- **Supports:** align (full, wide), anchor, ariaLabel, color (background, button, gradients, heading, link, text), dimensions (minHeight), layout (allowSizingOnChildren), position (sticky), spacing (blockGap, margin, padding), typography (fontSize, lineHeight), ~~html~~ - **Attributes:** allowedBlocks, tagName, templateLock ## Heading diff --git a/lib/block-supports/colors.php b/lib/block-supports/colors.php index 53213df34d9ffb..88e13abfc9cc9b 100644 --- a/lib/block-supports/colors.php +++ b/lib/block-supports/colors.php @@ -16,11 +16,13 @@ function gutenberg_register_colors_support( $block_type ) { $has_background_colors_support = true === $color_support || ( is_array( $color_support ) && _wp_array_get( $color_support, array( 'background' ), true ) ); $has_gradients_support = _wp_array_get( $color_support, array( 'gradients' ), false ); $has_link_colors_support = _wp_array_get( $color_support, array( 'link' ), false ); + $has_button_colors_support = _wp_array_get( $color_support, array( 'button' ), false ); $has_heading_colors_support = _wp_array_get( $color_support, array( 'heading' ), false ); $has_color_support = $has_text_colors_support || $has_background_colors_support || $has_gradients_support || $has_link_colors_support || + $has_button_colors_support || $has_heading_colors_support; if ( ! $block_type->attributes ) { diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php index 1e7f8aeda07be3..a743d83c2b5737 100644 --- a/lib/block-supports/elements.php +++ b/lib/block-supports/elements.php @@ -27,11 +27,15 @@ function gutenberg_render_elements_support( $block_content, $block ) { return $block_content; } - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); - $skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ); - $skip_heading_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ); - - if ( $skip_link_color_serialization && $skip_heading_color_serialization ) { + $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); + $skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ); + $skip_heading_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ); + $skip_button_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' ); + $skips_all_element_color_serialization = $skip_link_color_serialization && + $skip_heading_color_serialization && + $skip_button_color_serialization; + + if ( $skips_all_element_color_serialization ) { return $block_content; } @@ -77,7 +81,21 @@ function gutenberg_render_elements_support( $block_content, $block ) { foreach ( $heading_color_paths as $element_color_path ) { $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path, ), null ); - if ( null !== $element_color && $skip_heading_color_serialization ) { + if ( null !== $element_color && ! $skip_heading_color_serialization ) { + $element_colors_set++; + } + } + + $button_color_paths = array( + 'style.elements.button.color.text', + 'style.elements.button.color.background', + 'style.elements.button.color.gradient', + ); + + foreach ( $button_color_paths as $element_color_path ) { + $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path, ), null ); + + if ( null !== $element_color && ! $skip_button_color_serialization ) { $element_colors_set++; } } @@ -116,14 +134,18 @@ function gutenberg_render_elements_support_styles( $pre_render, $block ) { return null; } - $skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ); - $skip_heading_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ); + $skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ); + $skip_heading_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ); + $skip_button_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' ); + $skips_all_element_color_serialization = $skip_link_color_serialization && + $skip_heading_color_serialization && + $skip_button_color_serialization; - if ( $skip_link_color_serialization && $skip_heading_color_serialization ) { + if ( $skips_all_element_color_serialization ) { return null; } - $class_name = gutenberg_get_elements_class_name( $block ); + $class_name = gutenberg_get_elements_class_name( $block ); // Link colors $link_block_styles = isset( $element_block_styles['link'] ) ? $element_block_styles['link'] : null; @@ -170,6 +192,19 @@ function gutenberg_render_elements_support_styles( $pre_render, $block ) { } } + // Button colors + $button_block_styles = isset( $element_block_styles['button'] ) ? $element_block_styles['button'] : null; + + if ( ! $skip_button_color_serialization && $button_block_styles ) { + gutenberg_style_engine_get_styles( + $button_block_styles, + array( + 'selector' => ".$class_name .wp-element-button, .$class_name .wp-block-button__link", + 'context' => 'block-supports', + ) + ); + } + return null; } diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index e973186a975717..e0ae5fe46dd833 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -397,6 +397,12 @@ const withElementsStyles = createHigherOrderComponent( 'heading' ); + const skipButtonColorSerialization = shouldSkipSerialization( + props.name, + COLOR_SUPPORT_KEY, + 'button' + ); + const styles = useMemo( () => { // The .editor-styles-wrapper selector is required on elements styles. As it is // added to all other editor styles, not providing it causes reset and global @@ -460,6 +466,15 @@ const withElementsStyles = createHigherOrderComponent( selector: scopeSelector( baseElementSelector, ELEMENTS.h6 ), }, //TODO: Refactor this to a helper that can more concisely flesh out the rest of the heading elements. + { + styles: ! skipButtonColorSerialization + ? props.attributes.style?.elements?.button + : undefined, + selector: scopeSelector( + baseElementSelector, + ELEMENTS.button + ), + }, ]; const elementCssRules = []; for ( const { styles: elementStyles, selector } of elements ) { diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index a85c79a6e5277e..f81fc118ea84bb 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -167,6 +167,7 @@ export function useBlockSettings( name, parentLayout ) { const isLinkEnabled = useSetting( 'color.link' ); const isTextEnabled = useSetting( 'color.text' ); const isHeadingEnabled = useSetting( 'color.heading' ); + const isButtonEnabled = useSetting( 'color.button' ); const rawSettings = useMemo( () => { return { @@ -195,6 +196,7 @@ export function useBlockSettings( name, parentLayout ) { background: isBackgroundEnabled, link: isLinkEnabled, heading: isHeadingEnabled, + button: isButtonEnabled, text: isTextEnabled, }, typography: { diff --git a/packages/block-library/src/group/block.json b/packages/block-library/src/group/block.json index 4f8de8802ea70c..9c2d012620c3c1 100644 --- a/packages/block-library/src/group/block.json +++ b/packages/block-library/src/group/block.json @@ -31,6 +31,7 @@ "color": { "gradients": true, "heading": true, + "button": true, "link": true, "__experimentalDefaultControls": { "background": true, From 8353fc3e7158c10d0e4bdf9030cb4f06bcd05bb0 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:10:15 +1000 Subject: [PATCH 3/5] Linting fixes --- lib/block-supports/elements.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php index a743d83c2b5737..79c6f9f6581775 100644 --- a/lib/block-supports/elements.php +++ b/lib/block-supports/elements.php @@ -47,7 +47,7 @@ function gutenberg_render_elements_support( $block_content, $block ) { ); foreach ( $link_color_paths as $element_color_path ) { - $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path, ), null ); + $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path ), null ); if ( null !== $element_color && ! $skip_link_color_serialization ) { $element_colors_set++; @@ -79,7 +79,7 @@ function gutenberg_render_elements_support( $block_content, $block ) { ); foreach ( $heading_color_paths as $element_color_path ) { - $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path, ), null ); + $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path ), null ); if ( null !== $element_color && ! $skip_heading_color_serialization ) { $element_colors_set++; @@ -93,7 +93,7 @@ function gutenberg_render_elements_support( $block_content, $block ) { ); foreach ( $button_color_paths as $element_color_path ) { - $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path, ), null ); + $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path ), null ); if ( null !== $element_color && ! $skip_button_color_serialization ) { $element_colors_set++; @@ -147,7 +147,7 @@ function gutenberg_render_elements_support_styles( $pre_render, $block ) { $class_name = gutenberg_get_elements_class_name( $block ); - // Link colors + // Link colors. $link_block_styles = isset( $element_block_styles['link'] ) ? $element_block_styles['link'] : null; if ( ! $skip_link_color_serialization && $link_block_styles ) { @@ -170,7 +170,7 @@ function gutenberg_render_elements_support_styles( $pre_render, $block ) { } } - // Heading colors + // Heading colors. if ( ! $skip_heading_color_serialization ) { $heading_levels = array( 'heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ); @@ -192,7 +192,7 @@ function gutenberg_render_elements_support_styles( $pre_render, $block ) { } } - // Button colors + // Button colors. $button_block_styles = isset( $element_block_styles['button'] ) ? $element_block_styles['button'] : null; if ( ! $skip_button_color_serialization && $button_block_styles ) { From 17bac42e2013911b78b45bd70e10b454c4d8ac28 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:12:01 +1000 Subject: [PATCH 4/5] Another linting tweak --- lib/block-supports/elements.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php index 79c6f9f6581775..912664e154a342 100644 --- a/lib/block-supports/elements.php +++ b/lib/block-supports/elements.php @@ -176,7 +176,7 @@ function gutenberg_render_elements_support_styles( $pre_render, $block ) { foreach ( $heading_levels as $heading_level ) { $heading_block_styles = isset( $element_block_styles[ $heading_level ] ) ? $element_block_styles[ $heading_level ] : null; - $heading_selector = 'heading' !== $heading_level + $heading_selector = 'heading' !== $heading_level ? ".$class_name $heading_level" : ".$class_name h1, .$class_name h2, .$class_name h3, .$class_name h4, .$class_name h5, .$class_name h6"; From e36f1717a6e7cceb51674ec16dee7425c92bf6cf Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 25 Aug 2023 10:29:19 +1000 Subject: [PATCH 5/5] Consolidate element style generation for blocks If more than color styles are to be supported for elements on a per block instance basis, these refactors should make that much easier. --- lib/block-supports/elements.php | 204 +++++++++++------------ packages/block-editor/src/hooks/style.js | 183 +++++++++----------- 2 files changed, 184 insertions(+), 203 deletions(-) diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php index 912664e154a342..4029c91aa40a35 100644 --- a/lib/block-supports/elements.php +++ b/lib/block-supports/elements.php @@ -27,76 +27,71 @@ function gutenberg_render_elements_support( $block_content, $block ) { return $block_content; } - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); - $skip_link_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ); - $skip_heading_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ); - $skip_button_color_serialization = wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' ); - $skips_all_element_color_serialization = $skip_link_color_serialization && - $skip_heading_color_serialization && - $skip_button_color_serialization; - - if ( $skips_all_element_color_serialization ) { - return $block_content; - } - - $element_colors_set = 0; - - $link_color_paths = array( - 'style.elements.link.color.text', - 'style.elements.link.:hover.color.text', + $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); + + $element_color_properties = array( + 'button' => array( + 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' ), + 'paths' => array( + 'style.elements.button.color.text', + 'style.elements.button.color.background', + 'style.elements.button.color.gradient', + ), + ), + 'link' => array( + 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ), + 'paths' => array( + 'style.elements.link.color.text', + 'style.elements.link.:hover.color.text', + ), + ), + 'heading' => array( + 'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ), + 'paths' => array( + 'style.elements.heading.color.text', + 'style.elements.heading.color.background', + 'style.elements.heading.color.gradient', + 'style.elements.h1.color.text', + 'style.elements.h1.color.background', + 'style.elements.h1.color.gradient', + 'style.elements.h2.color.text', + 'style.elements.h2.color.background', + 'style.elements.h2.color.gradient', + 'style.elements.h3.color.text', + 'style.elements.h3.color.background', + 'style.elements.h3.color.gradient', + 'style.elements.h4.color.text', + 'style.elements.h4.color.background', + 'style.elements.h4.color.gradient', + 'style.elements.h5.color.text', + 'style.elements.h5.color.background', + 'style.elements.h5.color.gradient', + 'style.elements.h6.color.text', + 'style.elements.h6.color.background', + 'style.elements.h6.color.gradient', + ), + ), ); - foreach ( $link_color_paths as $element_color_path ) { - $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path ), null ); + $skip_all_element_color_serialization = $element_color_properties['button']['skip'] && + $element_color_properties['link']['skip'] && + $element_color_properties['heading']['skip']; - if ( null !== $element_color && ! $skip_link_color_serialization ) { - $element_colors_set++; - } + if ( $skip_all_element_color_serialization ) { + return $block_content; } - $heading_color_paths = array( - 'style.elements.heading.color.text', - 'style.elements.heading.color.background', - 'style.elements.heading.color.gradient', - 'style.elements.h1.color.text', - 'style.elements.h1.color.background', - 'style.elements.h1.color.gradient', - 'style.elements.h2.color.text', - 'style.elements.h2.color.background', - 'style.elements.h2.color.gradient', - 'style.elements.h3.color.text', - 'style.elements.h3.color.background', - 'style.elements.h3.color.gradient', - 'style.elements.h4.color.text', - 'style.elements.h4.color.background', - 'style.elements.h4.color.gradient', - 'style.elements.h5.color.text', - 'style.elements.h5.color.background', - 'style.elements.h5.color.gradient', - 'style.elements.h6.color.text', - 'style.elements.h6.color.background', - 'style.elements.h6.color.gradient', - ); - - foreach ( $heading_color_paths as $element_color_path ) { - $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path ), null ); + $element_colors_set = 0; - if ( null !== $element_color && ! $skip_heading_color_serialization ) { - $element_colors_set++; + foreach ( $element_color_properties as $element_config ) { + if ( $element_config['skip'] ) { + continue; } - } - - $button_color_paths = array( - 'style.elements.button.color.text', - 'style.elements.button.color.background', - 'style.elements.button.color.gradient', - ); - foreach ( $button_color_paths as $element_color_path ) { - $element_color = _wp_array_get( $block['attrs'], explode( '.', $element_color_path ), null ); - - if ( null !== $element_color && ! $skip_button_color_serialization ) { - $element_colors_set++; + foreach ( $element_config['paths'] as $path ) { + if ( null !== _wp_array_get( $block['attrs'], explode( '.', $path ), null ) ) { + $element_colors_set++; + } } } @@ -147,62 +142,67 @@ function gutenberg_render_elements_support_styles( $pre_render, $block ) { $class_name = gutenberg_get_elements_class_name( $block ); - // Link colors. - $link_block_styles = isset( $element_block_styles['link'] ) ? $element_block_styles['link'] : null; + $element_types = array( + 'button' => array( + 'selector' => ".$class_name .wp-element-button, .$class_name .wp-block-button__link", + 'skip' => $skip_button_color_serialization, + ), + 'link' => array( + 'selector' => ".$class_name a", + 'hover_selector' => ".$class_name a:hover", + 'skip' => $skip_link_color_serialization, + ), + 'heading' => array( + 'selector' => ".$class_name h1, .$class_name h2, .$class_name h3, .$class_name h4, .$class_name h5, .$class_name h6", + 'skip' => $skip_heading_color_serialization, + 'elements' => array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ), + ), + ); + + foreach ( $element_types as $element_type => $element_config ) { + if ( $element_config['skip'] ) { + continue; + } - if ( ! $skip_link_color_serialization && $link_block_styles ) { - gutenberg_style_engine_get_styles( - $link_block_styles, - array( - 'selector' => ".$class_name a", - 'context' => 'block-supports', - ) - ); + $element_style_object = _wp_array_get( $element_block_styles, array( $element_type ), null ); - if ( isset( $link_block_styles[':hover'] ) ) { + // Process primary element type styles. + if ( $element_style_object ) { gutenberg_style_engine_get_styles( - $link_block_styles[':hover'], + $element_style_object, array( - 'selector' => ".$class_name a:hover", + 'selector' => $element_config['selector'], 'context' => 'block-supports', ) ); - } - } - - // Heading colors. - if ( ! $skip_heading_color_serialization ) { - $heading_levels = array( 'heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ); - foreach ( $heading_levels as $heading_level ) { - $heading_block_styles = isset( $element_block_styles[ $heading_level ] ) ? $element_block_styles[ $heading_level ] : null; - $heading_selector = 'heading' !== $heading_level - ? ".$class_name $heading_level" - : ".$class_name h1, .$class_name h2, .$class_name h3, .$class_name h4, .$class_name h5, .$class_name h6"; - - if ( $heading_block_styles ) { + if ( isset( $element_style_object[':hover'] ) ) { gutenberg_style_engine_get_styles( - $heading_block_styles, + $element_style_object[':hover'], array( - 'selector' => $heading_selector, + 'selector' => $element_config['hover_selector'], 'context' => 'block-supports', ) ); } } - } - // Button colors. - $button_block_styles = isset( $element_block_styles['button'] ) ? $element_block_styles['button'] : null; - - if ( ! $skip_button_color_serialization && $button_block_styles ) { - gutenberg_style_engine_get_styles( - $button_block_styles, - array( - 'selector' => ".$class_name .wp-element-button, .$class_name .wp-block-button__link", - 'context' => 'block-supports', - ) - ); + // Process related elements e.g. h1-h6 for headings. + if ( isset( $element_config['elements'] ) ) { + foreach ( $element_config['elements'] as $element ) { + $element_style_object = _wp_array_get( $element_block_styles, array( $element ), null ); + + if ( $element_style_object ) { + gutenberg_style_engine_get_styles( + $element_style_object, + array( + 'selector' => ".$class_name $element", + 'context' => 'block-supports', + ) + ); + } + } + } } return null; diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index e0ae5fe46dd833..e165a888822948 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -372,6 +372,18 @@ export const withBlockControls = createHigherOrderComponent( 'withToolbarControls' ); +// Defines which element types are supported, including their hover styles or +// any other elements that have been included under a single element type +// e.g. heading and h1-h6. +const elementTypes = [ + { elementType: 'button' }, + { elementType: 'link', pseudo: [ ':hover' ] }, + { + elementType: 'heading', + elements: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ], + }, +]; + /** * Override the default block element to include elements styles. * @@ -383,116 +395,85 @@ const withElementsStyles = createHigherOrderComponent( const blockElementsContainerIdentifier = `wp-elements-${ useInstanceId( BlockListBlock ) }`; + + // The .editor-styles-wrapper selector is required on elements styles. As it is + // added to all other editor styles, not providing it causes reset and global + // styles to override element styles because of higher specificity. const baseElementSelector = `.editor-styles-wrapper .${ blockElementsContainerIdentifier }`; + const blockElementStyles = props.attributes.style?.elements; - const skipLinkColorSerialization = shouldSkipSerialization( - props.name, - COLOR_SUPPORT_KEY, - 'link' - ); + const styles = useMemo( () => { + if ( ! blockElementStyles ) { + return; + } - const skipHeadingColorSerialization = shouldSkipSerialization( - props.name, - COLOR_SUPPORT_KEY, - 'heading' - ); + const elementCSSRules = []; - const skipButtonColorSerialization = shouldSkipSerialization( - props.name, - COLOR_SUPPORT_KEY, - 'button' - ); + elementTypes.forEach( ( { elementType, pseudo, elements } ) => { + const skipSerialization = shouldSkipSerialization( + props.name, + COLOR_SUPPORT_KEY, + elementType + ); - const styles = useMemo( () => { - // The .editor-styles-wrapper selector is required on elements styles. As it is - // added to all other editor styles, not providing it causes reset and global - // styles to override element styles because of higher specificity. - const elements = [ - { - styles: ! skipLinkColorSerialization - ? props.attributes.style?.elements?.link - : undefined, - selector: `${ baseElementSelector } ${ ELEMENTS.link }`, - }, - { - styles: ! skipLinkColorSerialization - ? props.attributes.style?.elements?.link?.[ ':hover' ] - : undefined, - selector: `${ baseElementSelector } ${ ELEMENTS.link }:hover`, - }, - { - styles: ! skipHeadingColorSerialization - ? props.attributes.style?.elements?.heading - : undefined, - selector: scopeSelector( - baseElementSelector, - ELEMENTS.heading - ), - }, - { - styles: ! skipHeadingColorSerialization - ? props.attributes.style?.elements?.h1 - : undefined, - selector: scopeSelector( baseElementSelector, ELEMENTS.h1 ), - }, - { - styles: ! skipHeadingColorSerialization - ? props.attributes.style?.elements?.h2 - : undefined, - selector: scopeSelector( baseElementSelector, ELEMENTS.h2 ), - }, - { - styles: ! skipHeadingColorSerialization - ? props.attributes.style?.elements?.h3 - : undefined, - selector: scopeSelector( baseElementSelector, ELEMENTS.h3 ), - }, - { - styles: ! skipHeadingColorSerialization - ? props.attributes.style?.elements?.h4 - : undefined, - selector: scopeSelector( baseElementSelector, ELEMENTS.h4 ), - }, - { - styles: ! skipHeadingColorSerialization - ? props.attributes.style?.elements?.h5 - : undefined, - selector: scopeSelector( baseElementSelector, ELEMENTS.h5 ), - }, - { - styles: ! skipHeadingColorSerialization - ? props.attributes.style?.elements?.h6 - : undefined, - selector: scopeSelector( baseElementSelector, ELEMENTS.h6 ), - }, - //TODO: Refactor this to a helper that can more concisely flesh out the rest of the heading elements. - { - styles: ! skipButtonColorSerialization - ? props.attributes.style?.elements?.button - : undefined, - selector: scopeSelector( - baseElementSelector, - ELEMENTS.button - ), - }, - ]; - const elementCssRules = []; - for ( const { styles: elementStyles, selector } of elements ) { + if ( skipSerialization ) { + return; + } + + const elementStyles = blockElementStyles?.[ elementType ]; + + // Process primary element type styles. if ( elementStyles ) { - const cssRule = compileCSS( elementStyles, { - selector, + const selector = scopeSelector( + baseElementSelector, + ELEMENTS[ elementType ] + ); + + elementCSSRules.push( + compileCSS( elementStyles, { selector } ) + ); + + // Process any interactive states for the element type. + if ( pseudo ) { + pseudo.forEach( ( pseudoSelector ) => { + if ( elementStyles[ pseudoSelector ] ) { + elementCSSRules.push( + compileCSS( + elementStyles[ pseudoSelector ], + { + selector: scopeSelector( + baseElementSelector, + `${ ELEMENTS[ elementType ] }${ pseudoSelector }` + ), + } + ) + ); + } + } ); + } + } + + // Process related elements e.g. h1-h6 for headings + if ( elements ) { + elements.forEach( ( element ) => { + if ( blockElementStyles[ element ] ) { + elementCSSRules.push( + compileCSS( blockElementStyles[ element ], { + selector: scopeSelector( + baseElementSelector, + ELEMENTS[ element ] + ), + } ) + ); + } } ); - elementCssRules.push( cssRule ); } - } - return elementCssRules.length > 0 - ? elementCssRules.join( '' ) + } ); + + return elementCSSRules.length > 0 + ? elementCSSRules.join( '' ) : undefined; - }, [ - props.attributes.style?.elements, - baseElementSelector, - skipLinkColorSerialization, - ] ); + }, [ baseElementSelector, blockElementStyles, props.name ] ); const element = useContext( BlockList.__unstableElementContext );