Goo Tabs
betaDowel Tabs with a motion flourish: an icon bar whose pill stretches over the old and new tab, then snaps onto the new one, melted together by an SVG goo filter.
- Navigation
- 1 file
- 1 npm package
- Accessibility notes
Loading the example…
pnpm dlx @dowel-ui/cli add goo-tabsnpm packages installed: class-variance-authority.
import { GooTabs } from "@/components/ui/goo-tabs";Default
Gallery
Vertical
Plain Pill
Right To Left
<GooTabsList>
| Prop | Type | Default |
|---|---|---|
bounce0–100: overshoot of the settle phase. | number | 50 |
cornerRadius of the bar and the pill, in px. | number | 26 |
dilate0–100: how far the stretch phase reaches toward the full old→new span. 0 slides. | number | 100 |
gooMelt the pill and its trailing blob together with an SVG goo filter. | boolean | true |
hugPadding of the bar (the pill's inset), in px. | number | 6 |
speed0–100: stretch/settle take 304/672ms at 0, 190/420ms at 50, 76/168ms at 100. | number | 50 |
stroke | boolean | — |
tone | "default" | "inverted" | "default" |
A thin composition on Dowel's Tabs (Radix): role="tablist" (name it with aria-label) with one tab stop, arrow keys along the orientation that follow the reading direction, Home/End, wrap-around and automatic activation; tabs carry aria-selected and aria-controls, and panels are focusable. Icon-only tabs must be named with aria-label and warn in development when they are not; icons are decoration. The pill, trailing blob and goo filter are one aria-hidden layer that ignores the pointer, and the filter never applies to the icons. Under reduced motion (or without SVG filter support, or with goo={false}) the goo is dropped and the pill moves straight to the new tab.
10/10
checks passed
- Tested — passes
- axe assertion — passes
- Keyboard tested — passes
- Storybook examples — passes
- Accessibility documented — passes
- Semantic tokens only — passes
- Motion from tokens — passes
- className merged — passes
- Visible focus — passes
- No fixed widths — passes