Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/wp-includes/block-supports/states.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,42 @@ function wp_get_state_declarations_with_fallback_border_styles( $declarations )
return $declarations;
}

/**
* Adds background reset declarations to prevent gradient/solid color conflicts.
*
* When a state sets a solid background-color, any gradient applied to the
* default state (via `background` shorthand or `background-image`) must be
* explicitly cleared. Without this, the gradient image layer remains visible
* on top of the solid hover color even when `!important` is used, because
* `background-color` and `background-image` are separate CSS properties.
*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function needs an @since 7.1.0 tag here (see other functions in this file for comparison).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

* @since 7.1.0
*
* @param array $declarations CSS declarations generated by the style engine.
* @return array CSS declarations with background resets applied where needed.
*/
function wp_get_state_declarations_with_background_resets( $declarations ) {
if ( ! is_array( $declarations ) ) {
return $declarations;
}

$has_background_color = isset( $declarations['background-color'] ) && '' !== $declarations['background-color'];
$has_background = isset( $declarations['background'] ) && '' !== $declarations['background'];
$has_background_image = isset( $declarations['background-image'] ) && '' !== $declarations['background-image'];

/*
* When the state sets a solid background-color but no gradient of its own,
* emit `background-image: unset !important` to clear any gradient (whether
* stored as the `background` shorthand or as `background-image`) that was
* applied to the default / normal state via an inline style attribute.
*/
if ( $has_background_color && ! $has_background && ! $has_background_image ) {
$declarations['background-image'] = 'unset !important';
}

return $declarations;
}

/**
* Adds a style fragment to a selector-keyed state style group.
*
Expand Down Expand Up @@ -461,6 +497,7 @@ function wp_render_block_states_support( $block_content, $block ) {
: $value . ' !important';
}
$declarations = wp_get_state_declarations_with_fallback_border_styles( $declarations );
$declarations = wp_get_state_declarations_with_background_resets( $declarations );
$style_rule = array(
'selector' => wp_build_state_selector(
".$unique_class",
Expand Down
89 changes: 88 additions & 1 deletion tests/phpunit/tests/block-supports/states.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,93 @@ public function test_preserves_authored_border_style_declarations() {
);
}

/**
* Tests that background-image reset is added when a state sets a solid background-color.
*
* @covers ::wp_get_state_declarations_with_background_resets

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new tests should have @ticket 65239 tag (see other tests for comparison - 65239 being the trac ticket number this PR is linked with)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

*
* @ticket 65239
*/
public function test_adds_background_image_reset_for_solid_background_color() {
$actual = wp_get_state_declarations_with_background_resets(
array(
'background-color' => '#ff0000 !important',
)
);

$this->assertSame(
array(
'background-color' => '#ff0000 !important',
'background-image' => 'unset !important',
),
$actual
);
}

/**
* Tests that background-image reset is not added when the state also sets a legacy gradient.
*
* @covers ::wp_get_state_declarations_with_background_resets
*
* @ticket 65239
*/
public function test_no_background_image_reset_when_state_sets_legacy_gradient() {
$actual = wp_get_state_declarations_with_background_resets(
array(
'background-color' => '#ff0000 !important',
'background' => 'linear-gradient(135deg, #ff0000, #0000ff) !important',
)
);

$this->assertSame(
array(
'background-color' => '#ff0000 !important',
'background' => 'linear-gradient(135deg, #ff0000, #0000ff) !important',
),
$actual
);
}

/**
* Tests that background-image reset is not added when the state also sets a modern gradient.
*
* @covers ::wp_get_state_declarations_with_background_resets
*
* @ticket 65239
*/
public function test_no_background_image_reset_when_state_sets_modern_gradient() {
$actual = wp_get_state_declarations_with_background_resets(
array(
'background-color' => '#ff0000 !important',
'background-image' => 'linear-gradient(135deg, #ff0000, #0000ff) !important',
)
);

$this->assertSame(
array(
'background-color' => '#ff0000 !important',
'background-image' => 'linear-gradient(135deg, #ff0000, #0000ff) !important',
),
$actual
);
}

/**
* Tests that declarations without background-color are returned unchanged.
*
* @covers ::wp_get_state_declarations_with_background_resets
*
* @ticket 65239
*/
public function test_no_background_reset_when_no_background_color() {
$input = array(
'color' => '#ff0000 !important',
);
$actual = wp_get_state_declarations_with_background_resets( $input );

$this->assertSame( $input, $actual );
}

/**
* Tests that modifier classes on the first compound selector are preserved
* when state selectors are scoped to the block wrapper.
Expand Down Expand Up @@ -835,7 +922,7 @@ public function test_responsive_pseudo_state_generates_media_query_scoped_css()
$actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) );

$this->assertStringContainsString(
'@media (width <= 480px){.' . $matches[0] . ' .wp-block-button__link:hover{background-color:#ff00d0 !important;}}',
'@media (width <= 480px){.' . $matches[0] . ' .wp-block-button__link:hover{background-color:#ff00d0 !important;background-image:unset !important;}}',
$actual_stylesheet
);
}
Expand Down
Loading