From 825aca7a55673c034dcbc5b044d5a1f398de2f59 Mon Sep 17 00:00:00 2001 From: Ramon Date: Tue, 16 Jul 2024 12:21:51 +1000 Subject: [PATCH] Background: add background attachment to top level styles (#61382) Co-authored-by: ramonjd Co-authored-by: aaronrobertshaw Co-authored-by: jameskoster --- backport-changelog/6.7/6991.md | 3 ++ .../theme-json-reference/theme-json-living.md | 1 + lib/block-supports/background.php | 12 +++---- lib/class-wp-theme-json-gutenberg.php | 10 +++--- .../global-styles/background-panel.js | 22 ++++++++++++- .../components/global-styles/screen-block.js | 7 ++-- .../style-engine/class-wp-style-engine.php | 14 +++++--- .../src/styles/background/index.ts | 13 ++++++++ packages/style-engine/src/test/index.js | 6 ++++ phpunit/block-supports/background-test.php | 11 ++++--- phpunit/class-wp-theme-json-test.php | 33 ++++++++++--------- phpunit/style-engine/style-engine-test.php | 20 ++++++----- schemas/json/theme.json | 11 +++++++ 13 files changed, 115 insertions(+), 48 deletions(-) create mode 100644 backport-changelog/6.7/6991.md diff --git a/backport-changelog/6.7/6991.md b/backport-changelog/6.7/6991.md new file mode 100644 index 0000000000000..4d5f1f85ec768 --- /dev/null +++ b/backport-changelog/6.7/6991.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/6991 + +* https://github.com/WordPress/gutenberg/pull/61382 diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md index cf9ea9bc39113..d3f0b111d994d 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -216,6 +216,7 @@ Background styles. | backgroundPosition | string, object | | | backgroundRepeat | string, object | | | backgroundSize | string, object | | +| backgroundAttachment | string, object | | --- diff --git a/lib/block-supports/background.php b/lib/block-supports/background.php index 57b8d75f03d35..811608127f47e 100644 --- a/lib/block-supports/background.php +++ b/lib/block-supports/background.php @@ -52,12 +52,12 @@ function gutenberg_render_background_support( $block_content, $block ) { return $block_content; } - $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; - + $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; + $background_styles['backgroundAttachment'] = $block_attributes['style']['background']['backgroundAttachment'] ?? null; if ( ! empty( $background_styles['backgroundImage'] ) ) { $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`. diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 049b1c3e9124a..df46c3399a2a7 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -234,6 +234,7 @@ class WP_Theme_JSON_Gutenberg { 'background-position' => array( 'background', 'backgroundPosition' ), 'background-repeat' => array( 'background', 'backgroundRepeat' ), 'background-size' => array( 'background', 'backgroundSize' ), + 'background-attachment' => array( 'background', 'backgroundAttachment' ), 'border-radius' => array( 'border', 'radius' ), 'border-top-left-radius' => array( 'border', 'radius', 'topLeft' ), 'border-top-right-radius' => array( 'border', 'radius', 'topRight' ), @@ -503,10 +504,11 @@ class WP_Theme_JSON_Gutenberg { */ const VALID_STYLES = array( 'background' => array( - 'backgroundImage' => null, - 'backgroundPosition' => null, - 'backgroundRepeat' => null, - 'backgroundSize' => null, + 'backgroundImage' => null, + 'backgroundAttachment' => null, + 'backgroundPosition' => null, + 'backgroundRepeat' => null, + 'backgroundSize' => null, ), 'border' => array( 'color' => null, diff --git a/packages/block-editor/src/components/global-styles/background-panel.js b/packages/block-editor/src/components/global-styles/background-panel.js index 18ecc26b002d0..25ff5887eb5e6 100644 --- a/packages/block-editor/src/components/global-styles/background-panel.js +++ b/packages/block-editor/src/components/global-styles/background-panel.js @@ -451,6 +451,9 @@ function BackgroundSizeControls( { const positionValue = style?.background?.backgroundPosition || inheritedValue?.background?.backgroundPosition; + const attachmentValue = + style?.background?.backgroundAttachment || + inheritedValue?.background?.backgroundAttachment; /* * An `undefined` value is replaced with any supplied @@ -546,8 +549,17 @@ function BackgroundSizeControls( { ) ); + const toggleScrollWithPage = () => + onChange( + setImmutably( + style, + [ 'background', 'backgroundAttachment' ], + attachmentValue === 'fixed' ? 'scroll' : 'fixed' + ) + ); + return ( - + + ) } diff --git a/packages/style-engine/class-wp-style-engine.php b/packages/style-engine/class-wp-style-engine.php index 272c12705bf88..02186fecdcea2 100644 --- a/packages/style-engine/class-wp-style-engine.php +++ b/packages/style-engine/class-wp-style-engine.php @@ -42,31 +42,37 @@ final class WP_Style_Engine { */ const BLOCK_STYLE_DEFINITIONS_METADATA = array( 'background' => array( - 'backgroundImage' => array( + 'backgroundImage' => array( 'property_keys' => array( 'default' => 'background-image', ), 'value_func' => array( self::class, 'get_url_or_value_css_declaration' ), 'path' => array( 'background', 'backgroundImage' ), ), - 'backgroundPosition' => array( + 'backgroundPosition' => array( 'property_keys' => array( 'default' => 'background-position', ), 'path' => array( 'background', 'backgroundPosition' ), ), - 'backgroundRepeat' => array( + 'backgroundRepeat' => array( 'property_keys' => array( 'default' => 'background-repeat', ), 'path' => array( 'background', 'backgroundRepeat' ), ), - 'backgroundSize' => array( + 'backgroundSize' => array( 'property_keys' => array( 'default' => 'background-size', ), 'path' => array( 'background', 'backgroundSize' ), ), + 'backgroundAttachment' => array( + 'property_keys' => array( + 'default' => 'background-attachment', + ), + 'path' => array( 'background', 'backgroundAttachment' ), + ), ), 'color' => array( 'text' => array( diff --git a/packages/style-engine/src/styles/background/index.ts b/packages/style-engine/src/styles/background/index.ts index 6e79636cfda12..211b97343d89c 100644 --- a/packages/style-engine/src/styles/background/index.ts +++ b/packages/style-engine/src/styles/background/index.ts @@ -74,9 +74,22 @@ const backgroundSize = { }, }; +const backgroundAttachment = { + name: 'backgroundAttachment', + generate: ( style: Style, options: StyleOptions ) => { + return generateRule( + style, + options, + [ 'background', 'backgroundAttachment' ], + 'backgroundAttachment' + ); + }, +}; + export default [ backgroundImage, backgroundPosition, backgroundRepeat, backgroundSize, + backgroundAttachment, ]; diff --git a/packages/style-engine/src/test/index.js b/packages/style-engine/src/test/index.js index fbccc8c48bc92..f7960e19187a2 100644 --- a/packages/style-engine/src/test/index.js +++ b/packages/style-engine/src/test/index.js @@ -231,6 +231,7 @@ describe( 'getCSSRules', () => { backgroundPosition: '50% 50%', backgroundRepeat: 'no-repeat', backgroundSize: '300px', + backgroundAttachment: 'fixed', }, color: { text: '#dddddd', @@ -399,6 +400,11 @@ describe( 'getCSSRules', () => { key: 'backgroundSize', value: '300px', }, + { + selector: '.some-selector', + key: 'backgroundAttachment', + value: 'fixed', + }, ] ); } ); diff --git a/phpunit/block-supports/background-test.php b/phpunit/block-supports/background-test.php index 165a65204793d..33e72e9b07010 100644 --- a/phpunit/block-supports/background-test.php +++ b/phpunit/block-supports/background-test.php @@ -149,21 +149,22 @@ public function data_background_block_support() { 'expected_wrapper' => '
Content
', 'wrapper' => '
Content
', ), - 'background image style with contain, position, and repeat is applied' => array( + 'background image style with contain, position, attachment, and repeat is applied' => array( 'theme_name' => 'block-theme-child-with-fluid-typography', 'block_name' => 'test/background-rules-are-output', 'background_settings' => array( 'backgroundImage' => true, ), 'background_style' => array( - 'backgroundImage' => array( + 'backgroundImage' => array( 'url' => 'https://example.com/image.jpg', 'source' => 'file', ), - 'backgroundRepeat' => 'no-repeat', - 'backgroundSize' => 'contain', + 'backgroundRepeat' => 'no-repeat', + 'backgroundSize' => 'contain', + 'backgroundAttachment' => 'fixed', ), - 'expected_wrapper' => '
Content
', + 'expected_wrapper' => '
Content
', 'wrapper' => '
Content
', ), 'background image style is appended if a style attribute already exists' => array( diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 06892aab2e45a..d76517091f44f 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -4765,12 +4765,13 @@ public function test_get_top_level_background_image_styles() { 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'background' => array( - 'backgroundImage' => array( + 'backgroundImage' => array( 'url' => 'http://example.org/image.png', ), - 'backgroundSize' => 'contain', - 'backgroundRepeat' => 'no-repeat', - 'backgroundPosition' => 'center center', + 'backgroundSize' => 'contain', + 'backgroundRepeat' => 'no-repeat', + 'backgroundPosition' => 'center center', + 'backgroundAttachment' => 'fixed', ), ), ) @@ -4781,7 +4782,7 @@ public function test_get_top_level_background_image_styles() { 'selector' => 'body', ); - $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}"; + $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;background-attachment: fixed;}"; $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background styles do not match expectations' ); $theme_json = new WP_Theme_JSON_Gutenberg( @@ -4789,16 +4790,17 @@ public function test_get_top_level_background_image_styles() { 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( 'background' => array( - 'backgroundImage' => "url('http://example.org/image.png')", - 'backgroundSize' => 'contain', - 'backgroundRepeat' => 'no-repeat', - 'backgroundPosition' => 'center center', + 'backgroundImage' => "url('http://example.org/image.png')", + 'backgroundSize' => 'contain', + 'backgroundRepeat' => 'no-repeat', + 'backgroundPosition' => 'center center', + 'backgroundAttachment' => 'fixed', ), ), ) ); - $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}"; + $expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;background-attachment: fixed;}"; $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background image as string type do not match expectations' ); } @@ -4810,10 +4812,11 @@ public function test_get_block_background_image_styles() { 'blocks' => array( 'core/group' => array( 'background' => array( - 'backgroundImage' => "url('http://example.org/group.png')", - 'backgroundSize' => 'cover', - 'backgroundRepeat' => 'no-repeat', - 'backgroundPosition' => 'center center', + 'backgroundImage' => "url('http://example.org/group.png')", + 'backgroundSize' => 'cover', + 'backgroundRepeat' => 'no-repeat', + 'backgroundPosition' => 'center center', + 'backgroundAttachment' => 'fixed', ), ), 'core/quote' => array( @@ -4852,7 +4855,7 @@ public function test_get_block_background_image_styles() { ), ); - $group_styles = ":root :where(.wp-block-group){background-image: url('http://example.org/group.png');background-position: center center;background-repeat: no-repeat;background-size: cover;}"; + $group_styles = ":root :where(.wp-block-group){background-image: url('http://example.org/group.png');background-position: center center;background-repeat: no-repeat;background-size: cover;background-attachment: fixed;}"; $this->assertSame( $group_styles, $theme_json->get_styles_for_block( $group_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles as string type do not match expectations' ); } diff --git a/phpunit/style-engine/style-engine-test.php b/phpunit/style-engine/style-engine-test.php index 63e5b3c1c7f7f..fdf5ccebabef9 100644 --- a/phpunit/style-engine/style-engine-test.php +++ b/phpunit/style-engine/style-engine-test.php @@ -506,22 +506,24 @@ public function data_wp_style_engine_get_styles() { 'inline_background_image_url_with_background_size' => array( 'block_styles' => array( 'background' => array( - 'backgroundImage' => array( + 'backgroundImage' => array( 'url' => 'https://example.com/image.jpg', ), - 'backgroundPosition' => 'center', - 'backgroundRepeat' => 'no-repeat', - 'backgroundSize' => 'cover', + 'backgroundPosition' => 'center', + 'backgroundRepeat' => 'no-repeat', + 'backgroundSize' => 'cover', + 'backgroundAttachment' => 'fixed', ), ), 'options' => array(), 'expected_output' => array( - 'css' => "background-image:url('https://example.com/image.jpg');background-position:center;background-repeat:no-repeat;background-size:cover;", + 'css' => "background-image:url('https://example.com/image.jpg');background-position:center;background-repeat:no-repeat;background-size:cover;background-attachment:fixed;", 'declarations' => array( - 'background-image' => "url('https://example.com/image.jpg')", - 'background-position' => 'center', - 'background-repeat' => 'no-repeat', - 'background-size' => 'cover', + 'background-image' => "url('https://example.com/image.jpg')", + 'background-position' => 'center', + 'background-repeat' => 'no-repeat', + 'background-size' => 'cover', + 'background-attachment' => 'fixed', ), ), ), diff --git a/schemas/json/theme.json b/schemas/json/theme.json index f1666253e3de3..607228d65b80e 100644 --- a/schemas/json/theme.json +++ b/schemas/json/theme.json @@ -1220,6 +1220,17 @@ "$ref": "#/definitions/refComplete" } ] + }, + "backgroundAttachment": { + "description": "Sets the `background-attachment` CSS property.", + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/refComplete" + } + ] } }, "additionalProperties": false