# Spring Tab Bar

> Icon-only tab bar whose active tab grows its label on a spring; the panel above resizes and slides content in from the side you moved towards.

- Collection: Components
- Tier: pro
- Docs: https://geturui.com/docs/expandable-tabs
- Install: `npx shadcn@latest add @geturui-pro/expandable-tabs`
- Dependencies: motion

## Usage

```tsx
import { Calendar, Inbox, Settings } from "lucide-react";
import { ExpandableTabs } from "@/components/ui/expandable-tabs";

export function WorkspaceBar() {
  return (
    <ExpandableTabs
      aria-label="Workspace"
      className="w-[380px]"
      items={[
        { value: "inbox", label: "Inbox", icon: <Inbox />, content: <div className="p-4">3 unread</div> },
        { value: "calendar", label: "Calendar", icon: <Calendar />, content: <div className="p-4">2 events today</div> },
        { value: "settings", label: "Settings", icon: <Settings />, content: <div className="p-4">Pro plan</div> },
      ]}
    />
  );
}
```

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| items | `{ value: string; label: string; icon: ReactNode; content?: ReactNode }[]` | — | Tabs in order. label shows in the pill and names the icon button. |
| value | `string` | — | Controlled active tab. |
| defaultValue | `string` | items[0].value | Active tab on mount when uncontrolled. |
| onValueChange | `(value: string) => void` | — | Called when a tab is chosen by click or keyboard. |
| showPanel | `boolean` | true if any item has content | Render the morphing panel above the bar. |
| panelClassName | `string` | — | Classes for the panel surface. |
| aria-label | `string` | — | Names the tab list. |
| className | `string` | — | Classes for the outer column; set a width to size the panel. |

## Accessibility

- role="tablist" with role="tab" buttons, aria-selected and a roving tabindex; the panel is a role="tabpanel" labelled by its tab.
- Left and Right arrows (wrapping), Home and End move focus and select; each icon button is named by its label even when collapsed.
- With reduced motion the content crossfades without sliding or blur and the panel height snaps.

## Source

Pro item — send `Authorization: Bearer <registry token>` to include the source.
