Commit 0abde18
authored
feat(playground-ui): migrate Tabs to Base UI and add pill variant (#16414)
## Summary
- Migrates the `Tabs` component in `packages/playground-ui` from
`@radix-ui/react-tabs` to `@base-ui/react/tabs` (already a dep, used by
`Combobox`).
- Adds a new `pill` variant on `<TabList>` — animated background
indicator that slides behind the active trigger, à la the Base UI Tabs
demo.
- The default `line` variant now animates its underline smoothly between
tabs as well, using `<Tabs.Indicator>`.
- Public API (`Tabs`, `TabList`, `Tab`, `TabContent`) is unchanged —
existing call-sites keep the default `line` variant with no code change
required.
- Variant propagation is pure CSS via a `data-variant` attribute on
`TabList` plus Tailwind `group-data-[variant=...]/tabs-list:` selectors
— no React Context, no prop drilling.
### Usage
```tsx
<Tabs defaultTab="overview">
<TabList variant="pill">
<Tab value="overview">Overview</Tab>
<Tab value="projects">Projects</Tab>
<Tab value="account">Account</Tab>
</TabList>
<TabContent value="overview">…</TabContent>
</Tabs>
```
## Test plan
- [ ] `pnpm storybook` (from `packages/playground-ui`) → Navigation/Tabs
- [ ] Existing stories (Default, TwoTabs, ManyTabs, WithClosableTabs)
render and behave as before — underline now glides between tabs
- [ ] New `PillVariant` story — background pill slides fluidly between
triggers on click and on arrow-key navigation
- [ ] Existing call-sites unchanged visually:
- [ ] `CodeBlock` with `selector="tabs"`
- [ ] `span-data-panel-view` (traces detail panel)
- [ ] Metrics cards on agents page
- [ ] Keyboard a11y: Tab to enter, Arrow Left/Right to switch,
`data-active` present on active trigger
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## ELI5
The Tabs component is switched to a different internal library (Base UI)
and gets a new "pill" style where a colored background smoothly slides
behind the active tab; the default "line" style now animates its
underline smoothly. From the outside the component still works the same
so existing code doesn't need changes.
## Overview
This PR migrates the Tabs implementation in packages/playground-ui from
@radix-ui/react-tabs to @base-ui/react/tabs, adds a new TabList `pill`
variant with a sliding background indicator, and improves the `line`
variant to animate its underline between tabs. Public usage of Tabs
(Tabs, TabList, Tab, TabContent) remains compatible with existing call
sites.
## Implementation Details
- tabs-root.tsx
- Replaced Radix Root with BaseTabs.Root and removed internal
controlled/uncontrolled state management;
defaultValue/value/onValueChange are delegated to BaseTabs.
- tabs-list.tsx
- Introduces CVA-driven `tabListVariants` with `line` (default) and
`pill`.
- Adds a `variant` prop and sets `data-variant` on the list for Tailwind
group-data selectors.
- Renders BaseTabs.Indicator differently for `line` vs `pill` using CSS
variables for width/offset.
- ClassName handling changed so consumer `className` is applied to the
actual BaseTabs.List element (restores previous behavior via a
subsequent fix).
- tabs-tab.tsx
- Replaced Radix Trigger with BaseTabs.Tab and updated styles to rely on
Base UI data attributes (`data-[active]`, `data-[disabled]`) and the new
variant group selectors.
- Close-button behavior (stopPropagation + onClose) preserved.
- tabs-content.tsx
- Replaced Radix Content with BaseTabs.Panel; preserves `value` and
className behavior.
- tabs.stories.tsx
- Adds a `PillVariant` Storybook story demonstrating the new
`variant="pill"` usage.
Commit/fix note:
- fix(playground-ui): ensure consumer `className` is applied to the
actual TabList element (not only the outer scroll wrapper).
## Styling & Variant Propagation
Variant behavior is driven by a `data-variant` attribute on TabList and
targeted with Tailwind `group-data-[variant=...]/tabs-list:`
selectors—no React Context or prop drilling. CSS variables are used to
compute the active tab's width and left offset so the BaseTabs.Indicator
can animate smoothly for both `line` and `pill` visuals.
## Testing / Review Plan
- Visual: Storybook (Navigation/Tabs) including the new PillVariant
story; visual checks on existing call sites (CodeBlock selector="tabs",
span-data-panel-view, metrics cards).
- Interaction: Keyboard accessibility (Tab to focus, Arrow Left/Right to
change tabs), verify `data-[active]`/`data-active` state on active
trigger.
- Sanity: Ensure existing call sites render identically with default
styling and that the `pill` story shows the sliding background.
## Notes on API/Types
The outward component API remains compatible; callers do not need to
change. Internally TabList accepts a `variant` prop (typed via CVA's
VariantProps) to opt into `pill`, and className application to the list
element was corrected.
[](https://app.coderabbit.ai/change-stack/mastra-ai/mastra/pull/16414)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->1 parent a30ef7b commit 0abde18
6 files changed
Lines changed: 113 additions & 33 deletions
File tree
- .changeset
- packages/playground-ui/src/ds/components/Tabs
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
Lines changed: 3 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
19 | 19 | | |
20 | 20 | | |
Lines changed: 44 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
| 2 | + | |
| 3 | + | |
2 | 4 | | |
3 | 5 | | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
4 | 18 | | |
5 | 19 | | |
6 | 20 | | |
7 | | - | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
8 | 25 | | |
9 | | - | |
10 | 26 | | |
11 | | - | |
12 | | - | |
13 | | - | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
14 | 31 | | |
15 | 32 | | |
16 | | - | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
17 | 54 | | |
18 | 55 | | |
19 | 56 | | |
Lines changed: 8 additions & 18 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
| 1 | + | |
3 | 2 | | |
4 | 3 | | |
5 | 4 | | |
| |||
11 | 10 | | |
12 | 11 | | |
13 | 12 | | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | 13 | | |
29 | | - | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
30 | 20 | | |
31 | | - | |
| 21 | + | |
32 | 22 | | |
33 | 23 | | |
Lines changed: 12 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
| 17 | + | |
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
| 26 | + | |
27 | 27 | | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
28 | 35 | | |
29 | 36 | | |
30 | 37 | | |
| |||
42 | 49 | | |
43 | 50 | | |
44 | 51 | | |
45 | | - | |
| 52 | + | |
46 | 53 | | |
47 | 54 | | |
Lines changed: 21 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
85 | 106 | | |
86 | 107 | | |
87 | 108 | | |
| |||
0 commit comments