A styled tab selector component that renders a group of toggle buttons for switching between named views or modes, supporting icons, badges, two visual variants, and disabled states. ## Key Components ### `TabSelectorItem` Configuration object for each tab button: | Property | Type | Description | |---|---|---| | `id` | `string` | Unique identifier | | `label` | `string?` | Display text (omit for icon-only tabs) | | `ariaLabel` | `string?` | Required when `label` is omitted | | `icon` | `ReactNode?` | Leading icon | | `disabled` | `boolean?` | Disables this specific tab | | `badge` | `ReactNode?` | Trailing badge element | ### `TabSelectorProps` | Property | Type | Description | |---|---|---| | `value` | `string` | Currently selected tab id | | `onValueChange` | `(value: string) => void` | Selection change handler | | `items` | `TabSelectorItem[]` | Tabs to render | | `variant` | `'primary' \| 'secondary'` | Active tab highlight style (default: `'primary'`) | | `label` | `string?` | Optional heading above the selector | | `disabled` | `boolean?` | Disables the entire selector | | `scrollable` | `boolean?` | Horizontal scrolling + intrinsic-width tabs (for unbounded tab sets) | | `className` | `string?` | Additional root container classes | ### `TabSelector` The exported component. Renders a pill-style container with flex buttons — active tab receives accent background (`primary`) or surface background (`secondary`); inactive tabs are transparent with hover state. ## Usage Example ```typescript import { TabSelector, TabSelectorItem } from './tab-selector' import { LayoutGrid, List } from 'lucide-react' const tabs: TabSelectorItem[] = [ { id: 'grid', label: 'Grid', icon: }, { id: 'list', label: 'List', icon: }, { id: 'archive', label: 'Archive', disabled: true }, ] function ViewToggle() { const [view, setView] = React.useState('grid') return ( ) } ``` ## `scrollable` (added with the meeting-scheduler work) Horizontal-scroll mode for unbounded/dynamic tab sets: the row drops `w-full` for `overflow-x-auto`, items drop `flex-1` for `flex-none basis-auto shrink-0` (intrinsic widths must sum past the container or nothing ever overflows). Default layout unchanged.