Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8b0b379
Avatar: Explore colored fallbacks and foreground tinting
ciampo Oct 15, 2026
84f7250
Avatar: Link fallback exploration changelog entry
ciampo Oct 15, 2026
256646d
Avatar: Cover colors near the contrast crossover
ciampo Oct 15, 2026
4cadbae
Avatar: Compare translucent fallback foregrounds
ciampo Oct 15, 2026
8e7dad5
Avatar: Remove opacity exploration and improve neutral icon contrast
ciampo Oct 16, 2026
88a11c2
Avatar: Compare capped and uncapped fallback tinting
ciampo Oct 16, 2026
5d27d84
Avatar: Warn about unsupported fallback colors
ciampo Oct 16, 2026
563a3d3
Avatar: Target 3:1 contrast for person fallbacks
ciampo Oct 16, 2026
19426bf
Avatar: Use uncapped tinting and simplify color stories
ciampo Oct 16, 2026
0829e9b
Avatar: Match fallback borders to the person icon tint
ciampo Oct 16, 2026
ad2bbab
Avatar: Remove borders from colored fallbacks
ciampo Oct 16, 2026
7fca70e
Avatar: Consolidate colored examples in Storybook
ciampo Oct 16, 2026
69c4253
Avatar: Simplify colored Storybook examples
ciampo Oct 16, 2026
09465dd
Avatar: Keep color documentation focused on consumer use
ciampo Oct 19, 2026
9b11275
Avatar: Reduce stories and cover color behavior in browser tests
ciampo Oct 19, 2026
c6773f3
Avatar: Let Storybook infer available controls
ciampo Oct 19, 2026
29b133a
Avatar: Keep shared story args in the default example
ciampo Oct 19, 2026
3cf8c16
Avatar: Define the default render in its story
ciampo Oct 19, 2026
c27116c
Avatar: Use only inferred Storybook controls
ciampo Oct 19, 2026
38e192e
Merge branch 'trunk' into codex/avatar-fallback-tints
ciampo Oct 19, 2026
d6a266b
Avatar: Simplify the color prop description
ciampo Oct 19, 2026
5290b9c
Avatar: Use a typed Vitest mock for color warnings
ciampo Oct 19, 2026
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
2 changes: 2 additions & 0 deletions packages/ui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

### Enhancements

- `Avatar`: Use `color` for fallback backgrounds with contrasting text and icons ([#84824](https://github.com/WordPress/gutenberg/pull/84824)).
- `Avatar`: Add an optional `color` prop for an internal ring, preserving the avatar's layout size and neutral fallbacks while leaving room for an external focus ring ([#84822](https://github.com/WordPress/gutenberg/pull/84822)).
- `SelectControl`: Add a `trigger` slot and `SelectControl.Trigger` subcomponent for customizing trigger props ([#84828](https://github.com/WordPress/gutenberg/pull/84828)).
- `Link`: Use a small border radius for consistent focus rings in the default variant ([#84697](https://github.com/WordPress/gutenberg/pull/84697)).
Expand All @@ -32,6 +33,7 @@

### Bug Fixes

- `Avatar`: Use the strong neutral stroke color for the person fallback to provide sufficient non-text contrast ([#84824](https://github.com/WordPress/gutenberg/pull/84824)).
- `Tabs`: Expand vertical tab interaction backgrounds and focus rings across the row ([#84821](https://github.com/WordPress/gutenberg/pull/84821)).
- Keep the `Link` new-tab indicator with the preceding text when wrapping ([#84806](https://github.com/WordPress/gutenberg/pull/84806)).
- `Select`: Keep long popup lists scrollable when item alignment falls back to anchored positioning or the popup opens through touch ([#84682](https://github.com/WordPress/gutenberg/pull/84682)).
Expand Down
38 changes: 38 additions & 0 deletions packages/ui/src/avatar/dev-warnings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import warning from '@wordpress/warning';
import type { RootProps } from './types';

export function warnAvatarColor( color: RootProps[ 'color' ] ): void {
if ( color === undefined ) {
return;
}

// Skip comments and strings, and keep custom-property names as whole tokens.
// This is a best-effort scan; it does not decode CSS escapes or resolve var().
const tokens = color.match(
/\/\*[\s\S]*?(?:\*\/|$)|"(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'|(?:[-\w\u0080-\uFFFF]|\\(?:[\da-fA-F]{1,6}[ \t\r\n\f]?|[^\r\n\f]))+/g
);
if ( tokens?.some( ( token ) => token.toLowerCase() === 'currentcolor' ) ) {
warning(
'Avatar.Root: `color` contains `currentColor`, which can produce insufficient contrast in colored fallbacks. Use a color that does not depend on the foreground.'
);
return;
}

if ( typeof CSS === 'undefined' || ! CSS.supports ) {
return;
}

if ( ! CSS.supports( 'color', color ) ) {
warning(
'Avatar.Root: The browser does not support the `color` value. Use a valid CSS color supported by this browser.'
);
} else if (
// Browsers without relative colors retain the neutral fallback.
CSS.supports( 'color', 'rgb(from red r g b / 1)' ) &&
! CSS.supports( 'color', `rgb(from ${ color } r g b / 1)` )
) {
warning(
'Avatar.Root: `color` cannot be used as a colored fallback fill. Use an explicit CSS color instead of a CSS-wide keyword such as `inherit`.'
);
}
}
5 changes: 5 additions & 0 deletions packages/ui/src/avatar/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Avatar as _Avatar } from '@base-ui/react/avatar';
import clsx from 'clsx';
import { forwardRef } from '@wordpress/element';
import type { RootProps } from './types';
import { warnAvatarColor } from './dev-warnings';
import resetStyles from '../utils/css/resets.module.css';
import defenseStyles from '../utils/css/global-css-defense.module.css';
import styles from './style.module.css';
Expand All @@ -27,6 +28,10 @@ export const Root = forwardRef< HTMLSpanElement, RootProps >(
{ size = 'md', shape = 'circle', color, className, style, ...props },
ref
) {
if ( process.env.NODE_ENV !== 'production' ) {
warnAvatarColor( color );
}

const customProperties =
color === undefined
? style
Expand Down
Loading
Loading