Skip to content

Commit

Permalink
Global styles: block background UI controls (WordPress#60100)
Browse files Browse the repository at this point in the history
* Adding background panel for blocks.

* Default controls using block supports

* Updating tests after rebase
Removed unrequired change function

* Set defaults for the global styles block group background image

* Enabling theme file resolution for blocks

* LINTO

* Use global settings to check if background image is supported.

* This commit checks for theme block styles in the block supports hook so a background block control can determine whether it has an inherited value. If there is an inherited value, the block control will provide an option to "remove" the theme style.

This commit also sends resolved theme asset URI via the _links property so that these images can be used in block control previews.

Added resolver tests for blocks

Use `get_styles_for_block` in unit tests when testing block nodes

Use `get_styles_for_block` in unit tests when testing block nodes

Add since annotation

backport changelog

* update assertion comments

* Now that background styles can be used in block styles, move them to styles complete ref

* Pass resolved URIs to display inherited background image styles with relative paths
Also, output any background styles, even if there's no background image


Co-authored-by: ramonjd <[email protected]>
Co-authored-by: andrewserong <[email protected]>
Co-authored-by: tellthemachines <[email protected]>
Co-authored-by: aaronrobertshaw <[email protected]>
Co-authored-by: jasmussen <[email protected]>
Co-authored-by: jameskoster <[email protected]>
  • Loading branch information
7 people authored Jul 5, 2024
1 parent eaa7ed7 commit a1bef79
Show file tree
Hide file tree
Showing 19 changed files with 339 additions and 86 deletions.
3 changes: 3 additions & 0 deletions backport-changelog/6.7/6836.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
https://github.com/WordPress/wordpress-develop/pull/6836

* https://github.com/WordPress/gutenberg/pull/60100
13 changes: 13 additions & 0 deletions docs/reference-guides/theme-json-reference/theme-json-living.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,19 @@ Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-
## Styles


### background

Background styles.

| Property | Type | Props |
| --- | --- |--- |
| backgroundImage | string, object | |
| backgroundPosition | string, object | |
| backgroundRepeat | string, object | |
| backgroundSize | string, object | |

---

### border

Border styles.
Expand Down
12 changes: 6 additions & 6 deletions lib/block-supports/background.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ function gutenberg_render_background_support( $block_content, $block ) {
return $block_content;
}

$background_styles = array();
$background_styles['backgroundImage'] = isset( $block_attributes['style']['background']['backgroundImage'] ) ? $block_attributes['style']['background']['backgroundImage'] : array();
$background_styles = array();
$background_styles['backgroundImage'] = $block_attributes['style']['background']['backgroundImage'] ?? null;
$background_styles['backgroundSize'] = $block_attributes['style']['background']['backgroundSize'] ?? null;
$background_styles['backgroundPosition'] = $block_attributes['style']['background']['backgroundPosition'] ?? null;
$background_styles['backgroundRepeat'] = $block_attributes['style']['background']['backgroundRepeat'] ?? null;

if ( ! empty( $background_styles['backgroundImage'] ) ) {
$background_styles['backgroundSize'] = isset( $block_attributes['style']['background']['backgroundSize'] ) ? $block_attributes['style']['background']['backgroundSize'] : 'cover';
$background_styles['backgroundPosition'] = isset( $block_attributes['style']['background']['backgroundPosition'] ) ? $block_attributes['style']['background']['backgroundPosition'] : null;
$background_styles['backgroundRepeat'] = isset( $block_attributes['style']['background']['backgroundRepeat'] ) ? $block_attributes['style']['background']['backgroundRepeat'] : null;

$background_styles['backgroundSize'] = $background_styles['backgroundSize'] ?? 'cover';
// If the background size is set to `contain` and no position is set, set the position to `center`.
if ( 'contain' === $background_styles['backgroundSize'] && ! $background_styles['backgroundPosition'] ) {
$background_styles['backgroundPosition'] = 'center';
Expand Down
8 changes: 4 additions & 4 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -503,10 +503,10 @@ class WP_Theme_JSON_Gutenberg {
*/
const VALID_STYLES = array(
'background' => array(
'backgroundImage' => 'top',
'backgroundPosition' => 'top',
'backgroundRepeat' => 'top',
'backgroundSize' => 'top',
'backgroundImage' => null,
'backgroundPosition' => null,
'backgroundRepeat' => null,
'backgroundSize' => null,
),
'border' => array(
'color' => null,
Expand Down
33 changes: 31 additions & 2 deletions lib/class-wp-theme-json-resolver-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,7 @@ public static function get_style_variations( $scope = 'theme' ) {
* as the value of `_link` object in REST API responses.
*
* @since 6.6.0
* @since 6.7.0 Added support for resolving block styles.
*
* @param WP_Theme_JSON_Gutenberg $theme_json A theme json instance.
* @return array An array of resolved paths.
Expand All @@ -818,10 +819,11 @@ public static function get_resolved_theme_uris( $theme_json ) {

$theme_json_data = $theme_json->get_raw_data();

// Top level styles.
$background_image_url = $theme_json_data['styles']['background']['backgroundImage']['url'] ?? null;
// Using the same file convention when registering web fonts. See: WP_Font_Face_Resolver:: to_theme_file_uri.
$placeholder = 'file:./';

// Top level styles.
$background_image_url = $theme_json_data['styles']['background']['backgroundImage']['url'] ?? null;
if (
isset( $background_image_url ) &&
is_string( $background_image_url ) &&
Expand All @@ -840,6 +842,33 @@ public static function get_resolved_theme_uris( $theme_json ) {
$resolved_theme_uris[] = $resolved_theme_uri;
}

// Block styles.
if ( ! empty( $theme_json_data['styles']['blocks'] ) ) {
foreach ( $theme_json_data['styles']['blocks'] as $block_name => $block_styles ) {
if ( ! isset( $block_styles['background']['backgroundImage']['url'] ) ) {
continue;
}
$background_image_url = $block_styles['background']['backgroundImage']['url'] ?? null;
if (
isset( $background_image_url ) &&
is_string( $background_image_url ) &&
// Skip if the src doesn't start with the placeholder, as there's nothing to replace.
str_starts_with( $background_image_url, $placeholder ) ) {
$file_type = wp_check_filetype( $background_image_url );
$src_url = str_replace( $placeholder, '', $background_image_url );
$resolved_theme_uri = array(
'name' => $background_image_url,
'href' => sanitize_url( get_theme_file_uri( $src_url ) ),
'target' => "styles.blocks.{$block_name}.background.backgroundImage.url",
);
if ( isset( $file_type['type'] ) ) {
$resolved_theme_uri['type'] = $file_type['type'];
}
$resolved_theme_uris[] = $resolved_theme_uri;
}
}
}

return $resolved_theme_uris;
}

Expand Down
1 change: 1 addition & 0 deletions lib/global-styles-and-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ function gutenberg_add_global_styles_block_custom_css() {
function gutenberg_add_global_styles_for_blocks() {
global $wp_styles;
$tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data();
$tree = WP_Theme_JSON_Resolver_Gutenberg::resolve_theme_file_uris( $tree );
$block_nodes = $tree->get_styles_block_nodes();
foreach ( $block_nodes as $metadata ) {
$block_css = $tree->get_styles_for_block( $metadata );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ function BackgroundImageControls( {
inheritedValue,
onRemoveImage = noop,
displayInPanel,
themeFileURIs,
} ) {
const mediaUpload = useSelect(
( select ) => select( blockEditorStore ).getSettings().mediaUpload,
Expand Down Expand Up @@ -392,7 +393,10 @@ function BackgroundImageControls( {
name={
<InspectorImagePreviewItem
className="block-editor-global-styles-background-panel__image-preview"
imgUrl={ url }
imgUrl={ getResolvedThemeFilePath(
url,
themeFileURIs
) }
filename={ title }
label={ imgLabel }
/>
Expand Down Expand Up @@ -706,6 +710,7 @@ export default function BackgroundPanel( {
onChange={ onChange }
style={ value }
inheritedValue={ inheritedValue }
themeFileURIs={ themeFileURIs }
displayInPanel
onRemoveImage={ () => {
setIsDropDownOpen( false );
Expand All @@ -727,6 +732,7 @@ export default function BackgroundPanel( {
onChange={ onChange }
style={ value }
inheritedValue={ inheritedValue }
themeFileURIs={ themeFileURIs }
/>
) }
</div>
Expand Down
9 changes: 9 additions & 0 deletions packages/block-editor/src/components/global-styles/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,15 @@ export function useSettingsForBlockElement(
}
} );

[ 'backgroundImage', 'backgroundSize' ].forEach( ( key ) => {
if ( ! supportedStyles.includes( key ) ) {
updatedSettings.background = {
...updatedSettings.background,
[ key ]: false,
};
}
} );

updatedSettings.shadow = supportedStyles.includes( 'shadow' )
? updatedSettings.shadow
: false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { GlobalStylesContext } from './context';
import { useGlobalSetting } from './hooks';
import { getDuotoneFilter } from '../duotone/utils';
import { getGapCSSValue } from '../../hooks/gap';
import { setBackgroundStyleDefaults } from '../../hooks/background';
import { store as blockEditorStore } from '../../store';
import { LAYOUT_DEFINITIONS } from '../../layouts/definitions';
import { getValueFromObjectPath, setImmutably } from '../../utils/object';
Expand Down Expand Up @@ -387,6 +388,20 @@ export function getStylesDeclarations(
[]
);

/*
* Set background defaults.
* Applies to all background styles except the top-level site background.
*/
if ( ! isRoot && !! blockStyles.background ) {
blockStyles = {
...blockStyles,
background: {
...blockStyles.background,
...setBackgroundStyleDefaults( blockStyles.background ),
},
};
}

// The goal is to move everything to server side generated engine styles
// This is temporary as we absorb more and more styles into the engine.
const extraRules = getCSSRules( blockStyles );
Expand Down
29 changes: 25 additions & 4 deletions packages/block-editor/src/hooks/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import {
useHasBackgroundPanel,
hasBackgroundImageValue,
} from '../components/global-styles/background-panel';
import {
globalStylesDataKey,
globalStylesLinksDataKey,
} from '../store/private-keys';

export const BACKGROUND_SUPPORT_KEY = 'background';

Expand Down Expand Up @@ -134,10 +138,25 @@ export function BackgroundImagePanel( {
setAttributes,
settings,
} ) {
const style = useSelect(
( select ) =>
select( blockEditorStore ).getBlockAttributes( clientId )?.style,
[ clientId ]
const { style, inheritedValue, _links } = useSelect(
( select ) => {
const { getBlockAttributes, getSettings } =
select( blockEditorStore );
const _settings = getSettings();
return {
style: getBlockAttributes( clientId )?.style,
_links: _settings[ globalStylesLinksDataKey ],
/*
* @TODO 1. Pass inherited value down to all block style controls,
* See: packages/block-editor/src/hooks/style.js
* @TODO 2. Add support for block style variations,
* See implementation: packages/block-editor/src/hooks/block-style-variation.js
*/
inheritedValue:
_settings[ globalStylesDataKey ]?.blocks?.[ name ],
};
},
[ clientId, name ]
);

if (
Expand Down Expand Up @@ -165,12 +184,14 @@ export function BackgroundImagePanel( {

return (
<StylesBackgroundPanel
inheritedValue={ inheritedValue }
as={ BackgroundInspectorControl }
panelId={ clientId }
defaultValues={ BACKGROUND_DEFAULT_VALUES }
settings={ updatedSettings }
onChange={ onChange }
value={ style }
themeFileURIs={ _links?.[ 'wp:theme-file' ] }
/>
);
}
Expand Down
1 change: 1 addition & 0 deletions packages/block-editor/src/hooks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,6 @@ export { getSpacingClassesAndStyles } from './use-spacing-props';
export { getTypographyClassesAndStyles } from './use-typography-props';
export { getGapCSSValue } from './gap';
export { useCachedTruthy } from './use-cached-truthy';
export { setBackgroundStyleDefaults } from './background';
export { useZoomOut } from './use-zoom-out';
export { __unstableBlockStyleVariationOverridesWithConfig } from './block-style-variation';
4 changes: 4 additions & 0 deletions packages/block-editor/src/private-apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import BlockQuickNavigation from './components/block-quick-navigation';
import { LayoutStyle } from './components/block-list/layout';
import { BlockRemovalWarningModal } from './components/block-removal-warning-modal';
import {
setBackgroundStyleDefaults,
useLayoutClasses,
useLayoutStyles,
__unstableBlockStyleVariationOverridesWithConfig,
Expand All @@ -40,6 +41,7 @@ import {
selectBlockPatternsKey,
reusableBlocksSelectKey,
globalStylesDataKey,
globalStylesLinksDataKey,
} from './store/private-keys';
import { requiresWrapperOnCopy } from './components/writing-flow/utils';
import { PrivateRichText } from './components/rich-text/';
Expand Down Expand Up @@ -85,6 +87,7 @@ lock( privateApis, {
usesContextKey,
useFlashEditableBlocks,
globalStylesDataKey,
globalStylesLinksDataKey,
selectBlockPatternsKey,
requiresWrapperOnCopy,
PrivateRichText,
Expand All @@ -95,4 +98,5 @@ lock( privateApis, {
useSpacingSizes,
useBlockDisplayTitle,
__unstableBlockStyleVariationOverridesWithConfig,
setBackgroundStyleDefaults,
} );
1 change: 1 addition & 0 deletions packages/block-editor/src/store/private-keys.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const globalStylesDataKey = Symbol( 'globalStylesDataKey' );
export const globalStylesLinksDataKey = Symbol( 'globalStylesLinks' );
export const selectBlockPatternsKey = Symbol( 'selectBlockPatternsKey' );
export const reusableBlocksSelectKey = Symbol( 'reusableBlocksSelect' );
22 changes: 22 additions & 0 deletions packages/edit-site/src/components/global-styles/screen-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ import {
VariationsPanel,
} from './variations/variations-panel';

// Initial control values where no block style is set.
const BACKGROUND_BLOCK_DEFAULT_VALUES = {
backgroundSize: 'cover',
};

function applyFallbackStyle( border ) {
if ( ! border ) {
return border;
Expand Down Expand Up @@ -70,6 +75,8 @@ const {
useHasFiltersPanel,
useHasImageSettingsPanel,
useGlobalStyle,
useHasBackgroundPanel,
BackgroundPanel: StylesBackgroundPanel,
BorderPanel: StylesBorderPanel,
ColorPanel: StylesColorPanel,
TypographyPanel: StylesTypographyPanel,
Expand Down Expand Up @@ -121,6 +128,7 @@ function ScreenBlock( { name, variation } ) {
}

const blockVariations = useBlockVariations( name );
const hasBackgroundPanel = useHasBackgroundPanel( settings );
const hasTypographyPanel = useHasTypographyPanel( settings );
const hasColorPanel = useHasColorPanel( settings );
const hasBorderPanel = useHasBorderPanel( settings );
Expand Down Expand Up @@ -296,6 +304,20 @@ function ScreenBlock( { name, variation } ) {
/>
) }

{ hasBackgroundPanel && (
<StylesBackgroundPanel
inheritedValue={ inheritedStyle }
value={ style }
onChange={ setStyle }
settings={ settings }
defaultValues={ BACKGROUND_BLOCK_DEFAULT_VALUES }
defaultControls={
blockType?.supports?.background
?.__experimentalDefaultControls
}
/>
) }

{ canEditCSS && (
<PanelBody title={ __( 'Advanced' ) } initialOpen={ false }>
<p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ function ScreenLayout() {
const [ rawSettings ] = useGlobalSetting( '' );
const settings = useSettingsForBlockElement( rawSettings );
const hasDimensionsPanel = useHasDimensionsPanel( settings );
const hasBackgroundPanel = useHasBackgroundPanel( settings );
/*
* Use the raw settings to determine if the background panel should be displayed,
* as the background panel is not dependent on the block element settings.
*/
const hasBackgroundPanel = useHasBackgroundPanel( rawSettings );
return (
<>
<ScreenHeader title={ __( 'Layout' ) } />
Expand Down
Loading

0 comments on commit a1bef79

Please sign in to comment.