Skip to content

Prepare @wordpress/ui for use in Gutenberg #76135

Open

Description

@mirka

Note

The canonical source of component readiness is now the @wordpress/use-recommended-components lint rule. If you don't get a lint error for a given @wordpress/ui component, it's ready for use.

These are the remaining tasks before we can start using @wordpress/ui components in the Gutenberg app. Any other blockers will be added to this list as we discover them.

The official introduction of ThemeProvider and design tokens stylesheet needs separate planning, but is not technically a blocker to start component adoption.

Activity

  1. self-assigned this
    on Mar 4, 2026
  2. added
    [Type] Tracking IssueTactical breakdown of efforts across the codebase and/or tied to Overview issues.
    on Mar 4, 2026
  3. ciampo commented on Mar 6, 2026

    @ciampo
    Contributor

    @mirka should we also force imports from @wordpress/components to be renamed with a common prefix? ie.

    import { Button as WCButton } from '@wordpress/components';
    
    const { Menu as WCMenu } = unlock( privateComponentAPIs );

    We could then add an ESLint rule to nudge this renaming across codebases.

    This should make it easier to track usage / text search across the codebase without confusing naming collisions between @wordpress/components and @wordpress/ui ?

  4. mirka commented on Mar 9, 2026

    @mirka
    MemberAuthor

    force imports from @wordpress/components to be renamed with a common prefix?

    Added to the list 👍 We might need to go incrementally, given the quantity. Also maybe only rename the ones with clashing names.

  5. ciampo commented on Mar 17, 2026

    @ciampo
    Contributor

    Also flagged in #76570

  6. aduth commented on Apr 8, 2026

    @aduth
    Member

    @mirka Can you help me understand how you're suggesting we approach the allowlist in use-recommended-components? I noticed some usage of Link component in #73489 with circumvention of the lint rule, and it made me realize that I don't know why we do or do not want to allow usage of Link. In #76222 this was described as "ready for general use", but what does this mean in practical terms?

  7. mirka commented on Apr 8, 2026

    @mirka
    MemberAuthor

    A component goes in the allowlist when someone has verified to the best of their ability that it will work as expected in a WordPress environment, with no jarring differences between it and any @wordpress/components equivalent. I'm still finding new problems as I try to add components to the allowlist 😅 I can look at Link next — the only blocker I'm aware of was #76783, and with that out of the way hopefully it's just a matter of adding some migration guidance to the ExternalLink docs.

    Allowlist means ready to ship in Gutenberg. Not in allowlist means it's already known to be not ready to ship in Gutenberg, or nobody has verified it yet either way.

  8. senadir commented on Apr 10, 2026

    @senadir
    Contributor

    Should I proceed with #73489 or wait until this is fully resolved?

  9. ciampo commented on Apr 10, 2026

    @ciampo
    Contributor

    Should I proceed with #73489 or wait until this is fully resolved?

    @senadir I recommend you wait until Link is in the allow list, although that should be happening very soon (cc @mirka ?)

  10. aduth commented on Apr 20, 2026

    @aduth
    Member

    Left some notes about focus style compatibility and additional link coloring at #77012 (comment) :

    Putting together a quick example locally in Storybook, the two links have obvious differences side-by-side:

    image (Left is `@wordpress/ui` `Link`, right is `@wordpress/components` `ExternalLink`)
    Storybook code
    // packages/ui/src/link/stories/focus-ring-comparison.story.tsx
    
    import type { Meta, StoryObj } from '@storybook/react-vite';
    import { ExternalLink } from '@wordpress/components';
    import { Link } from '../index';
    
    const meta: Meta< typeof Link > = {
    	title: 'Design System/Components/Link/Focus ring comparison',
    	component: Link,
    };
    export default meta;
    
    type Story = StoryObj< typeof Link >;
    
    export const SideBySide: Story = {
    	render: () => (
    		<>
    			<Link href="#" openInNewTab>
    				WordPress.org
    			</Link>
    			<ExternalLink href="#">WordPress.org</ExternalLink>
    		</>
    	),
    };

    Aside from focus, another question is color. Do we want to backport the coloring we've applied to Link?

  11. aduth commented on May 26, 2026

    @aduth
    Member

    Tabs: Indicator color consistency with legacy tab components

    @mirka Was this addressed in #78418 ?

    Overlay components (popovers, dialogs, modals, tooltips, dropdowns...) need a compat layer

    My understanding is this compatibility is in place as of #77851 and is being applied to overlay components (#78372, #78375, #78356), with the last and current step being a confidence-growing sweep of migrations across 5 pull requests starting with #78411 (with the next two #78466 and #78470 also being merged at time of writing). At which point we'll consider this complete. Let me know if I've not accurately captured that @ciampo .

  12. ciampo commented on May 26, 2026

    @ciampo
    Contributor

    My understanding is this compatibility is in place as of #77851

    Only for some overlay components, ie. "leaf" overlays that are guaranteed not to spawn other overlays (ie. Tooltip, Select, Budugbox, Autocomplete, ...)

  13. aduth commented on Jul 1, 2026

    @aduth
    Member

    With alignment of button focus styles in #78646 and overflow Storybook E2E tests in #78256, how are we feeling about marking Button as recommended?

  14. mirka commented on Jul 1, 2026

    @mirka
    MemberAuthor

    Remaining items for Button are:

    1. Migrate to design tokens
    2. Decide what to do with shortcut handling
  15. simison commented on Jul 15, 2026

    @simison
    Member

    Is the UI Notice component's only pre-stable todos just to get UI Button stable, or was there more?

  16. mirka commented on Jul 15, 2026

    @mirka
    MemberAuthor

    Is the UI Notice component's only pre-stable todos just to get UI Button stable, or was there more?

    Yes, I haven't done a final review, but the Button tokenization is the only todo left that I'm aware of. The shortcut handling mentioned above is probably not a blocker in the context of Notice. I haven't assessed how much #79010 is going to be a blocker. Maybe it's fine.

  17. ciampo commented on Jul 15, 2026

    @ciampo
    Contributor

    Decide what to do with shortcut handling

    Assuming that actually reacting to keyboard shortcuts is out of scope (and something that should be handled separately from a UI component), what's left when dealing with shortcuts is

    • adding aria-keyshortcuts attribute on the interactive element that, when activated, would trigger the same action as the keyboard shortcut
    • displaying the symbols (with the correct styles) and labeling them appropriately for assistive technology
    • the above points implicitly require functionality to convert an OS-agnostic shortcut description into an OS-aware format, generating the three (related but different) necessary strings: display symbols, accessible label, aria-keyshortcuts compatible string

    We've had similar conversations in the past when talking about IconButton, and the same topic also caught my attention when working on Menu (which currently expects the consumer to integrate shortcuts "by hand", as shown in the Storybook examples from that PR).

    So far, we established that the "OS-agnostic to OS-aware strings" functionality is provided by @wordpress/keycodes (the APIs are currently a bit messy, but they get the job done, I believe)

    IconButton implements a shortcut prop:

    /**
    * The keyboard shortcut associated with this button. When provided, the
    * shortcut is displayed in the tooltip and announced to assistive technology.
    *
    * **Note**: This prop is for display and accessibility purposes only — the
    * consumer is responsible for implementing the actual keyboard event handler.
    */
    shortcut?: {
    /**
    * The human-readable representation of the shortcut, displayed in the
    * tooltip. Use platform-appropriate symbols (e.g., "⌘S" on macOS,
    * "Ctrl+S" on Windows).
    */
    displayShortcut: string;
    /**
    * The shortcut in a format compatible with the
    * [aria-keyshortcuts](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-keyshortcuts)
    * attribute. Use "+" to separate keys and standard key names
    * (e.g., "Meta+S", "Control+Shift+P").
    */
    ariaKeyShortcut: string;
    };

    This is convenient and works well for high-level components such as IconButton, but it's trickier for lower level components:

    • Button: we could add a IconButton-like shortcut prop, but it would imply that Button consumes Tooltip internally (unless we change the shortcut to be shown inline). Regardless, consumers wouldn't have the freedom of rendering a shortcut where they want (it will be forced by the component), which clashes with the low-level-iness of the Button component and how we generally expect consumers of these components to compose different components together.
    • Menu: this is potentially even trickier, because the aria-keyshortcuts attribute needs to be applied to the menu item, while the shortcut itself would normally go in the suffix. We could add the same shortcut prop on Menu.Item, and force-render the visual shortcut symbol in the suffix. It's not as clean and pure, but it could work.

    Separately / optionally, I still think it would be valuable to have a dedicated Shortcut UI component, for encapsulation and reusability across the DS.

  18. ciampo commented on Jul 15, 2026

    @ciampo
    Contributor

    Update: after speaking with @mirka:

    • aria-keyshortcuts is not enough for assistive technology, we need to provide a description of the keyboard shortcut separately. The best way is to use aria-describedby on the same element that received aria-keyshortcuts, and point to a visually hidden element that says something like "Keyboard shortcut: [shorcut accessible label]"
    • For that reason, the shortcut prop on IconButton should be expanded to recived an additional property for the shortcut accessible descrition, which can consume the result of the shortcutAriaLabel function from @wordpress/keycodes
    • For the Button component, we agreed that we should continue to show the shortcut in a tooltip, mostly for layout/screen estate reasons. But since we don't want to introduce a dependency on Tooltip in Button, mostly likely we are going to:
      • Initially, just add a Storybook example to Button showing how to manually hook up proper keyboard shortcuts
      • As a follow-up, work on a separate, dedicated ShortcutButton (name TBD) component which uses a Tooltip and has an API similar to IconButton (including a dedicated prop for the tooltip's contents)
    • For the Menu.Item component, we will try to adopt the same shortcut prop as done in IconButton, and handle the whole wiring internally. The visible shortcut will be added after the suffix slot
    • no shared Shortcut component for now, as all instances seem to render an aria-hidden element looking like a simple string of text

    Next steps:

  19. ciampo commented on Aug 10, 2026

    @ciampo
    Contributor

    Update re. keyboard shortcut handling:

    Considering @mirka 's recent work on focus rings, is there any work left before we mark Button (and potentially Notice) as stable and ready for use?

  20. mirka commented on Aug 11, 2026

    @mirka
    MemberAuthor

    I think we're pretty much ready for the Button family. I was thinking we should maybe have official migration guidance somewhere so it's more obvious how the old variants should map to the new ones. Maybe somewhere in Storybook, in the section for the old Button?

  21. ciampo commented on Aug 11, 2026

    @ciampo
    Contributor

    Agreed, that would be a nice touch!

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

Metadata

Metadata

Assignees

Labels

[Package] UI/packages/ui[Type] Tracking IssueTactical breakdown of efforts across the codebase and/or tied to Overview issues.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions