Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -400,22 +400,19 @@ export default function BackgroundImagePanel( {
key: 'background',
label: __( 'Color' ),
inheritedValue: backgroundColor,
// Resolve the slug from the same source as the
// displayed value (user value first, then the
// inherited fallback). For a block instance the
// selection lives in `value` while `inheritedValue`
// only holds the global styles fallback, so reading
// the slug from `inheritedValue` alone would miss it
// and two same-hex presets would both appear selected.
inheritedSlug:
extractPresetSlug(
value?.color?.background,
'color'
) ??
extractPresetSlug(
inheritedValue?.color?.background,
'color'
),
// The picker matches selection by slug, following
// whichever value is displayed: `userSlug` once a
// value is set, `inheritedSlug` at rest. Without
Comment thread
ramonjd marked this conversation as resolved.
Resolved
// the slugs it falls back to hex matching, which
// marks two same-hex presets as both selected.
inheritedSlug: extractPresetSlug(
inheritedValue?.color?.background,
'color'
),
userSlug: extractPresetSlug(
value?.color?.background,
'color'
),
setValue: setBackgroundColor,
userValue: userBackgroundColor,
isPlaceholder:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ function ColorGradientTab( {
isGradient,
inheritedValue,
inheritedSlug,
userSlug,
userValue,
setValue,
isPlaceholder,
Expand All @@ -142,6 +143,11 @@ function ColorGradientTab( {
// back to the inherited value so the at-rest preselection is visible
// inside the picker.
const displayed = userValue ?? inheritedValue;
// Selection inside the picker follows the slug of whichever value is
// displayed: the user slug once a value is set, the inherited slug at
// rest. Matching by slug keeps two same-hex presets apart; a slug-less
Comment thread
ramonjd marked this conversation as resolved.
Resolved
// (custom) value falls back to the picker's own hex matching.
const displayedSlug = userValue !== undefined ? userSlug : inheritedSlug;
// Display-without-commit interceptor. `ColorPalette` and `GradientPicker`
// fire `onChange( undefined )` when the user clicks the currently-selected
// option. At rest (placeholder mode), that click is the user's "accept
Expand All @@ -151,7 +157,7 @@ function ColorGradientTab( {
// set, the same click correctly clears local back to at rest.
const onChange = ( newValue, newSlug ) => {
if ( isPlaceholder && newValue === undefined ) {
setValue( inheritedValue );
setValue( inheritedValue, inheritedSlug );
return;
}
setValue( newValue, newSlug );
Expand All @@ -163,11 +169,7 @@ function ColorGradientTab( {
enableAlpha
__experimentalIsRenderedInSidebar
colorValue={ isGradient ? undefined : displayed }
colorSlug={
isGradient || userValue !== undefined
? undefined
: inheritedSlug
}
colorSlug={ isGradient ? undefined : displayedSlug }
gradientValue={ isGradient ? displayed : undefined }
onColorChange={ isGradient ? undefined : onChange }
onGradientChange={ isGradient ? onChange : undefined }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,10 @@ export default function ColorPanel( {
inheritedValue?.elements?.link?.color?.text,
'color'
),
userSlug: extractPresetSlug(
value?.elements?.link?.color?.text,
'color'
),
setValue: setLinkColor,
userValue: userLinkColor,
isPlaceholder:
Expand All @@ -338,6 +342,10 @@ export default function ColorPanel( {
?.text,
'color'
),
userSlug: extractPresetSlug(
value?.elements?.link?.[ ':hover' ]?.color?.text,
'color'
),
setValue: setHoverLinkColor,
userValue: userHoverLinkColor,
isPlaceholder:
Expand Down Expand Up @@ -476,6 +484,10 @@ export default function ColorPanel( {
inheritedValue?.elements?.[ name ]?.color?.text,
'color'
),
userSlug: extractPresetSlug(
value?.elements?.[ name ]?.color?.text,
'color'
),
setValue: setElementTextColor,
userValue: elementTextUserColor,
isPlaceholder: isElementTextPlaceholder,
Expand All @@ -490,6 +502,10 @@ export default function ColorPanel( {
?.background,
'color'
),
userSlug: extractPresetSlug(
value?.elements?.[ name ]?.color?.background,
'color'
),
setValue: setElementBackgroundColor,
userValue: elementBackgroundUserColor,
isPlaceholder: isElementBackgroundPlaceholder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* External dependencies
*/
import { render, renderHook, screen } from '@testing-library/react';
import { click, render as renderAriakit } from '@ariakit/test/react';

/**
* Internal dependencies
Expand Down Expand Up @@ -209,6 +210,50 @@ const baseSettings = {
},
};

describe( 'ColorPanel — duplicate-hex preset slug identity', () => {
const duplicateHexSettings = {
color: {
link: true,
defaultPalette: false,
palette: {
theme: [
{
slug: 'dark-background',
color: '#000000',
name: 'Dark background',
},
{ slug: 'dark-text', color: '#000000', name: 'Dark text' },
],
},
},
};

it( 'marks only the local link preset as selected when another preset shares its hex', async () => {
await renderAriakit(
<ColorPanel
value={ {
elements: {
link: {
color: { text: 'var:preset|color|dark-text' },
},
},
} }
settings={ duplicateHexSettings }
onChange={ () => {} }
panelId="test-panel"
/>
);

await click( screen.getByRole( 'button', { name: /^Link/ } ) );
const swatches = await screen.findAllByRole( 'option' );

// swatch[0] = 'Dark background', swatch[1] = 'Dark text'. Selection
// must follow the stored slug; matching by hex would mark both.
expect( swatches[ 1 ] ).toHaveAttribute( 'aria-selected', 'true' );
expect( swatches[ 0 ] ).toHaveAttribute( 'aria-selected', 'false' );
} );
} );

describe( 'ColorPanel — inherited Global Styles label treatment', () => {
describe( 'Link color', () => {
it( 'exposes an accessible reset when local link.text overrides the inherited value', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -739,16 +739,61 @@ const DUPLICATE_PALETTE_SETTINGS = {
},
};

describe( 'TypographyPanel — setTextColor link sync', () => {
// Helper: open the text Color dropdown and return the rendered swatches.
async function openTextColorDropdown() {
await click(
screen.getByRole( 'button', { name: /Color/, expanded: false } )
// Helper: open the text Color dropdown and return the rendered swatches.
async function openTextColorDropdown() {
await click(
screen.getByRole( 'button', { name: /Color/, expanded: false } )
);
// `findAllByRole` waits for the Popover/portal content to appear.
return screen.findAllByRole( 'option' );
}

describe( 'TypographyPanel — duplicate-hex preset slug identity', () => {
it( 'commits the inherited preset slug when accepting the preselected inherited color', async () => {
const onChange = jest.fn();

await renderAriakit(
<TypographyPanel
value={ {} }
inheritedValue={ {
color: { text: 'var:preset|color|dark-text' },
} }
settings={ DUPLICATE_PALETTE_SETTINGS }
panelId="test"
onChange={ onChange }
/>
);

const swatches = await openTextColorDropdown();
// swatch[1] ('Dark Text') is the preselected inherited option;
// activating it is the "accept inherited value" gesture. The commit
// must carry the inherited slug, not re-encode the shared #000 hex
// to whichever duplicate appears first in the palette.
await click( swatches[ 1 ] );

const result = onChange.mock.calls[ 0 ][ 0 ];
expect( result?.color?.text ).toBe( 'var:preset|color|dark-text' );
} );

it( 'marks only the local preset as selected when another preset shares its hex', async () => {
await renderAriakit(
<TypographyPanel
value={ { color: { text: 'var:preset|color|dark-text' } } }
settings={ DUPLICATE_PALETTE_SETTINGS }
panelId="test"
onChange={ jest.fn() }
/>
);
// `findAllByRole` waits for the Popover/portal content to appear.
return screen.findAllByRole( 'option' );
}

// swatch[0] = 'Dark Background', swatch[1] = 'Dark Text'. Selection
// must follow the stored slug; matching by hex would mark both.
const swatches = await openTextColorDropdown();
expect( swatches[ 1 ] ).toHaveAttribute( 'aria-selected', 'true' );
expect( swatches[ 0 ] ).toHaveAttribute( 'aria-selected', 'false' );
} );
} );

describe( 'TypographyPanel — setTextColor link sync', () => {
it( 'syncs the link color when text and link share the same raw preset reference', async () => {
const onChange = jest.fn();
const sharedRef = 'var:preset|color|dark-background';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -822,15 +822,14 @@ export default function TypographyPanel( {
key: 'text',
label: __( 'Color' ),
inheritedValue: textColor,
inheritedSlug:
extractPresetSlug(
value?.color?.text,
'color'
) ??
extractPresetSlug(
inheritedValue?.color?.text,
'color'
),
inheritedSlug: extractPresetSlug(
inheritedValue?.color?.text,
'color'
),
userSlug: extractPresetSlug(
value?.color?.text,
'color'
),
setValue: setTextColor,
userValue: userTextColor,
isPlaceholder:
Expand Down
Loading