WorkspaceTabs
Workspace tab bar with a gliding underline and per-tab actions.
WorkspaceTabs is the builder workspace’s pane switcher — Preview / Checkpoints / Usage in mono lowercase, a primary underline that glides between tabs (240ms ease-out, transform-only), and a right-aligned action slot that each tab owns: refresh belongs to the preview pane, “new checkpoint” to the timeline. Panes fade up 4px on entry; the bar itself never changes height. Built on the canonical shadcn tabs primitive, so keyboard navigation and ARIA come from Base UI.
Install
npx shadcn@latest add https://ui.neon.com/r/workspace-tabs.json
Usage
import { WorkspaceTabs } from "@/components/neon-ui/workspace-tabs";
<WorkspaceTabs
tabs={[
{
id: "preview",
label: "preview",
actions: (
<Button size="sm" variant="ghost">
Refresh
</Button>
),
content: <PreviewFrame src={sandboxUrl} title="Live preview" />,
},
{
id: "checkpoints",
label: "checkpoints",
count: checkpoints.length,
content: <CheckpointTimeline checkpoints={checkpoints} />,
},
{ id: "usage", label: "usage", content: <UsagePanel /> },
]}
/>;
Props
PropType
tabsWorkspaceTab[]
id, label, content, plus optional icon, count, actions, and disabled per tab.
Type
WorkspaceTab[]value?string
Controlled active tab id.
Type
stringdefaultValue?string
Uncontrolled initial tab id.
Type
stringDefault
first tabonValueChange?(id: string) => void
Called with the tab id on switch.
Type
(id: string) => voidAccessibility
- Base UI tabs semantics:
tablist/tab/tabpanelwiring, arrow-key navigation, and focus management come from the primitive. - The gliding underline and action crossfade are decorative (
aria-hidden) and static underprefers-reduced-motion. - Counts render as plain text inside the tab, so they’re announced with the label.