Skip to content

UI: Use solid brand highlights for popup items - #84087

Merged
ciampo merged 17 commits into
trunkfrom
codex/composite-focus-comparison
Oct 23, 2026
Merged

ciampo merged 17 commits into
trunkfrom
codex/composite-focus-comparison

Conversation

@ciampo

@ciampo ciampo commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

See #80405. The @wordpress/components work remains in #84583. Popup alignment is reviewed separately in #84935.

What?

Use the same solid brand highlight for hovered and keyboard-highlighted popup items in @wordpress/ui.

Why?

Give popup items one consistent highlight without separate item focus rings or custom interaction tracking.

How?

Use the active foreground and background tokens from the solid brand Button. Supporting text, icons, and selection indicators use the same foreground. Style Base UI's active item through [data-highlighted], so a stationary pointer does not leave a second row filled during keyboard navigation. Open submenu parents use the solid highlight while active and retain the subtle neutral background after focus moves into the submenu.

Testing Instructions

  1. Open the Menu Rich Items, Link Item, Checkbox Items, Radio Items, and Submenu stories. Hover items. Expect a solid brand background with contrasting text, icons, descriptions, and shortcuts. Disabled items keep their disabled appearance. Hover an open submenu parent and expect the same solid brand highlight. Move into its submenu and expect the parent to return to light gray while the active child uses the solid brand highlight.
  2. Open the Select With Item Description, Combobox Default, Autocomplete With Item Descriptions, and searchable select and chip-select stories, including their control compositions. Hover options. Expect the same highlight and readable supporting text.
  3. Repeat in light, dark, and custom themes, with primary #608010 and background #4f386e. Enable WordPress global CSS and check RTL. In forced-colors mode, active items use the system highlight colors. Resting open submenu parents retain a thin system-color outline.

Testing Instructions for Keyboard

  1. Tab to each trigger or input, open its popup, and use the arrow keys. Expect the same highlight as hover, with no separate item ring. Editable inputs retain their own focus ring.
  2. In Combobox Default, open the popup, hover Apple, leave the pointer still, and press ArrowDown. Only Apricot should have the solid highlight, and Enter should select Apricot. Reopen, move the pointer to another option, and press Enter. That option becomes the active target and is selected. Dismiss with Escape.
  3. Check Menu links, checkbox and radio items, and submenus with the keyboard. Confirm selection and dismissal still work. An active submenu parent uses the solid brand highlight. Once focus moves into its submenu, the parent returns to the subtle neutral background.
  4. In Autocomplete Grid, filter to grinning, press ArrowDown, hover the cell, and press ArrowDown again. The active cell keeps its highlight at the grid boundary.
  5. Set highlightItemOnHover={ false } on Menu or Combobox. Hovering another item should not add a second fill or change the keyboard target. Enter should still activate the keyboard-highlighted item.
Verification

Production build, CSS lint, changelog validation, commit hooks, and 215 existing popup tests passed for the latest follow-up. Independent review found no remaining actionable issues. Chromium checks confirmed one active highlight during pointer-to-keyboard switching, Enter selection, submenu active and resting states, supporting content, disabled items, and menu links, including dark mode, WordPress global CSS, RTL, and forced colors.

Earlier Chromium checks covered all nine popup and control variants, custom themes, the autocomplete grid, heading-rendered labels, and ARIA-disabled menu links. Those checks measured highlighted text contrast at 6.00:1 in light, 4.58:1 in dark, and 5.62:1 in the custom theme. Safari, touch, screen readers, and native Windows high-contrast mode were not tested.

Screenshots or screencast

Before: trunk 5e25c6a584a. After: b70ab55e928. These popup appearances are unchanged by the later label, disabled-link, and submenu-parent fixes. Matching standalone Storybook captures at 500 × 440, cropped to the relevant content, LTR, basic global CSS. The first option is hovered.

Menu, Select, and Combobox highlights before and after in the light theme

Dark theme, searchable compositions, and controls

Menu, Select, and Combobox highlights before and after in the dark theme

Autocomplete, SearchableSelect, and SearchableChipSelect highlights before and after

SelectControl, SearchableSelectControl, and SearchableChipSelectControl highlights before and after

Open submenu parent

Menu Submenu, captured at eaceeaa5112, light theme, WordPress global CSS loaded with wp-admin/wp-core-ui classes, LTR, 900 × 480. The open parent stays light gray while a child uses the solid brand highlight. In the current implementation, the parent uses the solid brand highlight when it becomes the active item.

Light gray open submenu parent with a solid brand highlighted child

Use of AI Tools

Under the author's direction, Codex reworked the styles, removed the earlier interaction-tracking code, rebased the branch, ran verification and an independent review, captured screenshots, addressed review feedback, and updated this description.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

🎉 Props

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: ciampo <mciampini@git.wordpress.org>
Co-authored-by: mirka <0mirka00@git.wordpress.org>
Co-authored-by: fcoveram <fcoveram@git.wordpress.org>
Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
Co-authored-by: jasmussen <joen@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Updated as activity occurs, without notifying anyone named here. Add the props-bot label to refresh.

📦 Bundle size

Size Change: +12 B (0%)

Total Size: 9.06 MB

📦 View Changed
Filename Size Change
build/modules/core-fields/post_type_supports.min.js 81.8 kB +42 B (+0.05%)
build/modules/workflow/index.min.js 89.2 kB +59 B (+0.07%)
build/scripts/block-editor/index.min.js 606 kB -84 B (-0.01%)
build/scripts/block-library/index.min.js 449 kB +109 B (+0.02%)
build/scripts/components/index.min.js 372 kB -39 B (-0.01%)
build/scripts/edit-site/index.min.js 424 kB -117 B (-0.03%)
build/scripts/editor/index.min.js 620 kB +40 B (+0.01%)
build/scripts/format-library/index.min.js 90.2 kB +23 B (+0.03%)
build/scripts/media-utils/index.min.js 265 kB -49 B (-0.02%)
build/scripts/widgets/index.min.js 72.6 kB +28 B (+0.04%)

3465adc Run

🏁 Flaky tests

Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

Regression: updating a specific option will only change its value and will not corrupt others in /test/e2e/specs/editor/various/core-settings.spec.js, passed after 1 failed attempt.
Error: expect(received).toStrictEqual(expected) // deep equality

- Expected  - 1
+ Received  + 1

  Array [
    "rewrite_rules",
-   "SERIALIZED DATA",
+   "",
  ]
    at forEach (/home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:46:26)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:43:35

3465adc Run

@ciampo

ciampo commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor Author

@WordPress/gutenberg-components @WordPress/gutenberg-design @Mamaduka Here's a POC to test diffent options for hover / focus states, trying out a few alternatives:

  • neutral vs brand color
  • focus ring vs indicator
Screen.Recording.2026-10-05.at.22.36.44.mov

I personally quite like the neutral version, it feels like it blends better, doesn't scream for attention and leaves the primary color for the instances where it really needs to gran the attention.

@ciampo ciampo added the [Type] Enhancement A suggestion for improvement. label Oct 7, 2026
@ciampo ciampo self-assigned this Oct 7, 2026
@ciampo

ciampo commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Unless there are objections, I'd like to move forward with using a neutral background color for the highlight, and using a focus ring around items that receive keyboard focus (which means that in combobox-like UIs, there may be two focus rings displayed at once, but that should be ok).

I plan on iterating on this tomorrow, unless there are any objections.

@fcoveram

fcoveram commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Nice ✨ Great work.

neutral background color for the highlight, and using a focus ring around items that receive keyboard focus (which means that in combobox-like UIs, there may be two focus rings displayed at once, but that should be ok).

+1 to this. I don't think two rings is a problem. I like that they share the same hierarchy level. If then we need to change it, then the marker in blue also looks good to me.

One thing I noticed, and where I might have missed the conversation, is that the brand variant is darker, compared to the light blue I see in the storybook of Menu. No matter the hue value, I assume the hover state when triggering a submenu should follow whatever style is applied to hover.

Light blue Submenu interaction
CleanShot 2026-10-07 at 17 13 23@2x CleanShot 2026-10-07 at 17 12 55@2x

@ciampo

ciampo commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

One thing I noticed, and where I might have missed the conversation, is that the brand variant is darker, compared to the light blue I see in the storybook of Menu. No matter the hue value, I assume the hover state when triggering a submenu should follow whatever style is applied to hover.

The brand variant is darker because it mimics the previous active styles, basically same as solid brand buttons. For submenu parent items, I honestly haven't thought about it, so I'd be open to feedback in that case.

Still, that shouldn't be an issue if we go with neutral highlights (which seems to have general consensus from what I gathered)

@ciampo
ciampo force-pushed the codex/composite-focus-comparison branch from 4ab0f18 to e6ffca5 Compare October 8, 2026 16:26
@github-actions github-actions Bot added [Package] Components /packages/components [Package] UI /packages/ui labels Oct 8, 2026
@ciampo ciampo changed the title Design system: Compare composite focus indicators Design system: Use neutral highlights and focus rings for popup items Oct 8, 2026
@ciampo
ciampo requested review from a team, Mamaduka and t-hamano and a balanced review from Copilot October 8, 2026 20:50
@ciampo
ciampo marked this pull request as ready for review October 8, 2026 20:52
@ciampo
ciampo requested a review from a team as a code owner October 8, 2026 20:52

Copilot AI left a comment

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.

🔵 Needs a closer look

The broad cross-package focus and forced-colors behavior warrants final human browser review.

0 open findings

What changed in this PR

Standardizes popup item highlights and keyboard focus rings across @wordpress/ui and @wordpress/components.

Changes:

  • Applies neutral hover/highlight colors and zero-offset focus rings.
  • Tracks pointer versus keyboard interaction for composite options.
  • Updates themed popup backgrounds and package changelogs.
File Description
packages/​ui/​src/​utils/​use-popup-pointer-highlight.ts Tracks popup pointer interaction.
packages/​ui/​src/​utils/​item-popup/​keyboard-highlight-context.ts Shares keyboard-highlight state.
packages/​ui/​src/​utils/​css/​item-popup.module.css Updates generic popup item styles.
packages/​ui/​src/​menu/​style.module.css Updates menu highlights and rings.
packages/​ui/​src/​menu/​popup.tsx Adds pointer tracking to menus.
packages/​ui/​src/​form/​primitives/​select/​popup.tsx Adds pointer tracking to selects.
packages/​ui/​src/​form/​primitives/​combobox/​root.tsx Tracks combobox keyboard highlighting.
packages/​ui/​src/​form/​primitives/​combobox/​item.tsx Exposes combobox highlight modality.
packages/​ui/​src/​form/​primitives/​autocomplete/​root.tsx Tracks autocomplete keyboard highlighting.
packages/​ui/​src/​form/​primitives/​autocomplete/​item.tsx Exposes autocomplete highlight modality.
packages/​ui/​CHANGELOG.md Records UI package changes.
packages/​components/​src/​utils/​hooks/​use-keyboard-navigation.ts Adds shared navigation tracking.
packages/​components/​src/​utils/​composite-item.scss Defines shared popup state styles.
packages/​components/​src/​utils/​colors-values.js Adds focus and highlight tokens.
packages/​components/​src/​menu/​styles.ts Updates deprecated menu states.
packages/​components/​src/​menu-item/​style.scss Applies shared menu-item styles.
packages/​components/​src/​form-token-field/​types.ts Adds keyboard-navigation state prop.
packages/​components/​src/​form-token-field/​suggestions-list.tsx Marks keyboard-driven suggestion lists.
packages/​components/​src/​form-token-field/​style.scss Updates suggestion item styling.
packages/​components/​src/​form-token-field/​index.tsx Tracks suggestion interaction modality.
packages/​components/​src/​dropdown/​style.scss Themes dropdown popup items.
packages/​components/​src/​dropdown-menu/​style.scss Updates dropdown menu items.
packages/​components/​src/​custom-select-control-v2/​style.module.scss Updates custom select option states.
packages/​components/​src/​combobox-control/​index.tsx Tracks combobox interaction modality.
packages/​components/​src/​autocomplete/​style.scss Updates autocomplete option states.
packages/​components/​src/​autocomplete/​autocompleter-ui.tsx Tracks editor autocomplete navigation.
packages/​components/​CHANGELOG.md Records Components package changes.

🧠 Review effort: Balanced


💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

@mirka

mirka commented Oct 12, 2026

Copy link
Copy Markdown
Member

Should we split this into at least two PRs (wp-ui and wp-components)? Given the maintenance aspect, I feel like this warrants some consideration/review of the approach itself, not just the rendered result.

@ciampo

ciampo commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

As far as we have agreement on the overall approach, sure.

I just didn't want to end up with inconsistencies again.

@ciampo ciampo changed the title Design system: Use neutral highlights and focus rings for popup items UI: Use neutral highlights and focus rings for popup items Oct 12, 2026
@github-actions github-actions Bot removed the [Package] Components /packages/components label Oct 12, 2026
@ciampo

ciampo commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor Author

I moved the @wordpress/components changes to a separate PR (#84583).

This PR stays focused on @wordpress/ui, and is ready for review.

@jameskoster

Copy link
Copy Markdown
Contributor

+1 for neutral :)

@jameskoster

Copy link
Copy Markdown
Contributor

We could make this theme-able, like shadcn/ui. But not something to worry about here/now.

@ciampo

ciampo commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor Author

@jameskoster this PR should be in a good state for a full review, it implements neutral bg/fg colors + visible focus ring (see PR description for screenshots)

@jameskoster

Copy link
Copy Markdown
Contributor

It's looking good to me. Dark mode is especially a big improvement.

The main issue is the untidy alignment here, but it's not the fault of this PR:

Screenshot 2026-10-13 at 16 08 46

@ciampo
ciampo force-pushed the codex/composite-focus-comparison branch from eaceeaa to 3ca82f6 Compare October 23, 2026 06:26
Comment thread packages/ui/src/utils/css/item-popup.module.css Outdated
Comment thread packages/ui/CHANGELOG.md Outdated
Comment thread packages/ui/src/menu/style.module.css Outdated
@ciampo
ciampo requested a review from mirka October 23, 2026 12:17

@mirka mirka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Happy we were able to align on a solution that's not too painful! 💛

@ciampo
ciampo merged commit 50868bf into trunk Oct 23, 2026
101 of 107 checks passed
@ciampo
ciampo deleted the codex/composite-focus-comparison branch October 23, 2026 13:34
@github-project-automation github-project-automation Bot moved this from 🔎 Needs Review to ✅ Done in WordPress 7.2 Editor Tasks Oct 23, 2026
@github-actions github-actions Bot added this to the Gutenberg 24.4 milestone Oct 23, 2026
@github-actions github-actions Bot removed the Backport to WP 7.2 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Oct 23, 2026
gutenbergplugin pushed a commit that referenced this pull request Oct 23, 2026
* Storybook: Compare composite focus indicators

* Design system: Use neutral highlights and focus rings for popup items

* Design system: Fix changelog section ordering

* UI: Share popup highlight tracking and handle same-item pointer hover

* UI: Keep virtual popup focus rings with the input focus

* Combobox: Align popup search fields with items

* Combobox: Inset option highlights without changing the search field

* UI: Share input and list highlight handlers

* Autocomplete: Restore focus ring at grid boundaries

* UI: Extract popup option alignment for separate review

* UI: Separate keyboard option rings from pointer hover

* UI: Simplify active option rings to input focus

* UI: Use solid brand highlights for popup items

* UI: Preserve popup colors for headings and disabled links

* Menu: Keep open submenu parents neutral when highlighted

* UI: Restore submenu hover and join adjacent highlights

* UI: Keep popup highlights on the active item

---

Co-authored-by: ciampo <mciampini@git.wordpress.org>
Co-authored-by: mirka <0mirka00@git.wordpress.org>
Co-authored-by: fcoveram <fcoveram@git.wordpress.org>
Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
Co-authored-by: jasmussen <joen@git.wordpress.org>
@github-actions github-actions Bot added the Backported to WP Core Pull request that has been successfully merged into WP Core label Oct 23, 2026
@github-actions

Copy link
Copy Markdown

I just cherry-picked this PR to the wp/7.2 branch to get it included in the next release: d22ef52

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backport to Gutenberg RC Pull request that needs to be backported to a Gutenberg release candidate (RC) Backported to WP Core Pull request that has been successfully merged into WP Core [Package] UI /packages/ui [Type] Enhancement A suggestion for improvement.

Projects

Development

Successfully merging this pull request may close these issues.

7 participants