-
Notifications
You must be signed in to change notification settings - Fork 4.7k
@wordpress/ui: add Tabs
#74652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@wordpress/ui: add Tabs
#74652
Conversation
|
Size Change: 0 B Total Size: 3 MB ℹ️ View Unchanged
|
| /* Appearance */ | ||
| cursor: pointer; | ||
|
|
||
| /* Typography (TODO: replace with theme tokens when available) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will follow-up in a separate PR to use typography DS tokens (maybe after updating Text)
| } | ||
|
|
||
| [data-orientation="horizontal"] & { | ||
| padding-inline: calc(4 * var(--wpds-dimension-base)); /* TODO: Use or create new control/interactive padding token */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we should wait before using dimension DS tokens to make sure we have a revised approach going forward (see #74556)
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Flaky tests detected in afcac15. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/21519447368
|
bc97837 to
63f19e5
Compare
c5ee9e7 to
36bb104
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Adds a new Tabs primitive to @wordpress/ui, adapting behavior and patterns from @wordpress/components to the newer UI package conventions.
Changes:
- Introduces
Tabscomponents (Root,List,Tab,Panel) with styling, Storybook stories, and extensive unit tests. - Extends the shared
ComponentPropstyping to support Base UIrenderstate typing, and updates several existing primitives’ types accordingly. - Adds
@wordpress/composeas a dependency (and TS project reference) to supportuseMergeRefsusage inTabs.List.
Reviewed changes
Copilot reviewed 19 out of 20 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/ui/tsconfig.json | Adds @wordpress/compose TS project reference for build correctness. |
| packages/ui/src/utils/types.ts | Extends ComponentProps typing to support render state. |
| packages/ui/src/tabs/types.ts | Defines public prop types for the new Tabs primitives. |
| packages/ui/src/tabs/root.tsx | Adds Tabs.Root wrapper around Base UI Tabs. |
| packages/ui/src/tabs/list.tsx | Adds Tabs.List with overflow detection, masking, indicator rendering, and render override support. |
| packages/ui/src/tabs/tab.tsx | Adds Tabs.Tab with chevron affordance and styling hooks. |
| packages/ui/src/tabs/panel.tsx | Adds Tabs.Panel wrapper and styling. |
| packages/ui/src/tabs/style.module.css | Implements visual styles, focus styles, indicator styling, and overflow masking. |
| packages/ui/src/tabs/stories/index.story.tsx | Adds Storybook stories for default/compact/vertical/overflow cases and composition examples. |
| packages/ui/src/tabs/stories/best-practices.mdx | Adds usage guidance for controlled/uncontrolled modes. |
| packages/ui/src/tabs/test/index.test.tsx | Adds comprehensive behavior/a11y/interaction tests. |
| packages/ui/src/tabs/index.ts | Exposes the Tabs subcomponents. |
| packages/ui/src/index.ts | Exports Tabs namespace from the package root. |
| packages/ui/src/form/primitives/input/types.ts | Updates typing to pass Base UI state through ComponentProps. |
| packages/ui/src/form/primitives/fieldset/types.ts | Updates typing to pass Base UI state through ComponentProps. |
| packages/ui/src/form/primitives/field/types.ts | Updates typing to pass Base UI state through ComponentProps. |
| packages/ui/src/button/types.ts | Updates typing to pass Base UI state through ComponentProps. |
| packages/ui/package.json | Adds @wordpress/compose dependency required by Tabs.List. |
| packages/ui/CHANGELOG.md | Documents the addition of the Tabs primitive. |
| package-lock.json | Updates lockfile to reflect dependency graph changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
5d3c3cd to
afcac15
Compare
…e, like Base UI" This reverts commit 36bb104.
aduth
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM after latest round of updates 👍 Few minor comments.
|
|
||
| const MyUncontrolledTabs = () => ( | ||
| <Tabs.Root | ||
| onValueChange={ ( tab ) => console.log( 'New selected tab: ', tab ) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside: I feel like we're missing some documentation on our approach to onValueChange vs. onChange props, since historical components used onChange for what we're now using onValueChange (i.e. value vs. raw event).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. This feels like something to coordinate at the package level, especially related to our Form components (cc @mirka )
I guess it's up to us to decide how detailed we want our first-party documentation to be vs delagating to indivisual types docs vs linking to Base UI docs (if relevant)
891e088 to
f9dc3f4
Compare
f9dc3f4 to
71bb020
Compare
* Initial commit * Fix imports react => @wordpress/elements import order * Add export * Adjust --wpds-color-stroke-interactive-neutral-strong * CHANGELOG * Fix stylelint errors * Add @wordpress/compose to the UI package * Unify tests, fix lint errors * Update package.json * remove cursor files (added by mistake) * Restore tooltip in stories * Move best practices file * Fix storybook mdx * Revert "Adjust --wpds-color-stroke-interactive-neutral-strong" This reverts commit 9ef48ac. * Fix docs * Remove custom focusable prop in favour of using tabIndex directly * Use Icon component instead of cloning an SVG * Fix renamed DS tokens * Use ComponentProps utility type * Support a second "State" argument in internal render prop type, like Base UI * Use underscore notation for Base UI imports * Fix unit tests * Simplify overflow measurement (remove unnecessary variables and checks) * remove stale CHANGELOG entry * Remove wrong package references * Revert "Support a second "State" argument in internal render prop type, like Base UI" This reverts commit 36bb104. * Do not forward state in the render prop * Update snippet * Fix changelog * Refactor from `density="compact"` to `variant="minimal"` * Move useState inside render function in docs code snippet * Follow Base UI renaming convention * Cleaner tabIndex fix in tests * Fix RTL edge fade when scrolling horizontally * Simplify tabIndex calculation for tablist * Do not use BEM * Simplify Storybook --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: aduth <aduth@git.wordpress.org>
|
Nice to see this. As a follow-up, I'd love a final answer on whether to use this component or to build a NavigationList variant in the different site editor pages, knowing that these are "links" and we kind of want them to look as tabs (according to design) |
|
First instinct is that we shouldn't use |
* Initial commit * Fix imports react => @wordpress/elements import order * Add export * Adjust --wpds-color-stroke-interactive-neutral-strong * CHANGELOG * Fix stylelint errors * Add @wordpress/compose to the UI package * Unify tests, fix lint errors * Update package.json * remove cursor files (added by mistake) * Restore tooltip in stories * Move best practices file * Fix storybook mdx * Revert "Adjust --wpds-color-stroke-interactive-neutral-strong" This reverts commit 9ef48ac. * Fix docs * Remove custom focusable prop in favour of using tabIndex directly * Use Icon component instead of cloning an SVG * Fix renamed DS tokens * Use ComponentProps utility type * Support a second "State" argument in internal render prop type, like Base UI * Use underscore notation for Base UI imports * Fix unit tests * Simplify overflow measurement (remove unnecessary variables and checks) * remove stale CHANGELOG entry * Remove wrong package references * Revert "Support a second "State" argument in internal render prop type, like Base UI" This reverts commit 36bb104. * Do not forward state in the render prop * Update snippet * Fix changelog * Refactor from `density="compact"` to `variant="minimal"` * Move useState inside render function in docs code snippet * Follow Base UI renaming convention * Cleaner tabIndex fix in tests * Fix RTL edge fade when scrolling horizontally * Simplify tabIndex calculation for tablist * Do not use BEM * Simplify Storybook --- Co-authored-by: ciampo <mciampini@git.wordpress.org> Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: jameskoster <jameskoster@git.wordpress.org> Co-authored-by: aduth <aduth@git.wordpress.org>
What?
Add
Tabscomponent to@wordpress/uiWhy?
We're building a new set of UI primitives, see #71196
How?
Take the good parts of
Tabsfrom@wordpress/componentsand adapt it to the new conventions / DS tokens / etcTesting Instructions
Check code, unit tests, smoke test in Storybook
Screenshots or screencast
Next Steps
Textor DS tokens once finalized