Tabs
01 Preview
02 Usage
View switcher. Amber underline marks the active tab; add index for zero-padded ordinals.
Give each item content and Tabs renders a real ARIA tabs widget — tablist/tab/tabpanel,
roving tabindex, arrow-key navigation — and owns the switching itself:
<Tabs
index
aria-label="Sections"
defaultValue="work"
items={[
{ id: 'work', label: 'Work', content: <WorkList /> },
{ id: 'writing', label: 'Writing', content: <Essays /> },
{ id: 'about', label: 'About', content: <Bio /> },
]}
/>Without content it renders a plain navigation rail and deliberately drops the tab roles —
role="tab" pointing at no panel reads worse to a screen reader than no role at all. Use that
form only when something else does the switching, and wire the panel yourself:
<Tabs
aria-label="Sections"
value={view}
items={[
{ id: 'work', label: 'Work' },
{ id: 'writing', label: 'Writing' },
]}
onChange={(id) => setView(id)}
/>Prefer the content form. Always pass aria-label (or aria-labelledby): with panels it names
the role="tablist"; without them the rail takes role="group" so the name is exposed rather
than sitting inert on a role-less div. Unnamed and panel-less, it stays a plain <div> and
claims nothing.
Controlled: value + onChange. Uncontrolled: defaultValue only.
03 Props
| Prop | Type | Default | Notes |
|---|---|---|---|
| items* | TabItem[] |
— | — |
| value | string |
— | Active tab id (controlled). |
| defaultValue | string |
— | Initial active tab id (uncontrolled). Defaults to the first item. |
| onChange | (id: string) => void |
— | Fires with the selected tab id. |
| index | boolean |
false |
Prefix each tab with a zero-padded index. |
| aria-label | string |
— | Accessible name for the tab rail. |
Also accepts every attribute of Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> — they are spread onto the root element. className is merged, not replaced, and ref is forwarded.
04 TabItem
| Prop | Type | Default | Notes |
|---|---|---|---|
| id* | string |
— | — |
| label* | React.ReactNode |
— | — |
| content | React.ReactNode |
— | Panel body for this tab. Supply it on every item to get a real tab/tabpanel widget. |
05 Import
import { Tabs } from '@denizarsan/darsan.design';
import '@denizarsan/darsan.design/styles.css';