Tabs
Switch between mutually exclusive content panels via tabbed navigation.
Selectors
[data-tabs]- Container for the tab group. Activates
cider.jsbehavior. [data-tab-list]- Optional wrapper for tab buttons. Falls back to the first button's parent element. Receives
role="tablist". [data-tab="id"]- Tab button. The value links to a matching
[data-tab-panel]. [data-tab-panel="id"]- Content panel toggled by the active tab. Hidden when inactive.
[data-tab-indicator]- Optional sliding indicator positioned by JS (used by Segmented Control).
[data-active]- Marks the initially active tab and panel.
Default
General settings content.
Notification preferences content.
Security settings content.
<div data-tabs>
<div data-tab-list class="flex gap-1 border-b border-border-solid pb-px">
<button data-tab="t1" data-active class="px-3 py-1.5 text-sm font-medium border-b-2 border-primary text-primary -mb-px">General</button>
<button data-tab="t2" class="px-3 py-1.5 text-sm text-tertiary-foreground hover:text-foreground border-b-2 border-transparent -mb-px">Notifications</button>
<button data-tab="t3" class="px-3 py-1.5 text-sm text-tertiary-foreground hover:text-foreground border-b-2 border-transparent -mb-px">Security</button>
</div>
<div data-tab-panel="t1" data-active>
<p class="py-4 text-sm text-tertiary-foreground">General settings content.</p>
</div>
<div data-tab-panel="t2">
<p class="py-4 text-sm text-tertiary-foreground">Notification preferences content.</p>
</div>
<div data-tab-panel="t3">
<p class="py-4 text-sm text-tertiary-foreground">Security settings content.</p>
</div>
</div>
Disabled Tab
This tab is active. The "Locked" tab cannot be selected.
This tab is available.
This panel is unreachable.
<div data-tabs>
<div data-tab-list class="flex gap-1 border-b border-border-solid pb-px">
<button data-tab="d1" data-active class="px-3 py-1.5 text-sm font-medium border-b-2 border-primary text-primary -mb-px">Active</button>
<button data-tab="d2" class="px-3 py-1.5 text-sm text-tertiary-foreground hover:text-foreground border-b-2 border-transparent -mb-px">Available</button>
<button data-tab="d3" disabled class="px-3 py-1.5 text-sm text-tertiary-foreground border-b-2 border-transparent -mb-px opacity-40 cursor-not-allowed">Locked</button>
</div>
<div data-tab-panel="d1" data-active>
<p class="py-4 text-sm text-tertiary-foreground">This tab is active. The "Locked" tab cannot be selected.</p>
</div>
<div data-tab-panel="d2">
<p class="py-4 text-sm text-tertiary-foreground">This tab is available.</p>
</div>
<div data-tab-panel="d3">
<p class="py-4 text-sm text-tertiary-foreground">This panel is unreachable.</p>
</div>
</div>
Vertical
Profile settings. Arrow Up/Down navigate tabs in vertical orientation.
Account settings content.
Billing information content.
<div data-tabs class="flex gap-6">
<div data-tab-list data-orientation="vertical" class="flex flex-col gap-1 border-r border-border-solid pr-4 min-w-[120px]">
<button data-tab="v1" data-active class="px-3 py-1.5 text-sm font-medium text-left text-primary bg-primary/10 rounded-[var(--radius-sm)]">Profile</button>
<button data-tab="v2" class="px-3 py-1.5 text-sm text-left text-tertiary-foreground hover:text-foreground hover:bg-secondary/50 rounded-[var(--radius-sm)]">Account</button>
<button data-tab="v3" class="px-3 py-1.5 text-sm text-left text-tertiary-foreground hover:text-foreground hover:bg-secondary/50 rounded-[var(--radius-sm)]">Billing</button>
</div>
<div data-tab-panel="v1" data-active class="flex-1">
<p class="text-sm text-tertiary-foreground">Profile settings. Arrow Up/Down navigate tabs in vertical orientation.</p>
</div>
<div data-tab-panel="v2" class="flex-1">
<p class="text-sm text-tertiary-foreground">Account settings content.</p>
</div>
<div data-tab-panel="v3" class="flex-1">
<p class="text-sm text-tertiary-foreground">Billing information content.</p>
</div>
</div>
Usage
Tabs is a behavioral layer — it manages activation, ARIA attributes, and keyboard navigation. Visual styling is up to you (Tailwind utilities, custom CSS, or the Segmented Control component).
Keyboard
| Key | Action |
|---|---|
| Arrow Right / Arrow Left | Move to next / previous tab (horizontal orientation) |
| Arrow Down / Arrow Up | Move to next / previous tab (vertical orientation) |
| Home | Move to first tab |
| End | Move to last tab |
| Enter / Space | Activate focused tab |
Accessibility
- Sets
role="tablist",role="tab", androle="tabpanel"automatically. - Manages
aria-selected,aria-controls,aria-labelledby, andtabindexroving focus. - Set
data-orientation="vertical"on[data-tab-list]for vertical arrow key navigation. - Disabled tabs (
disabledoraria-disabled="true") are skipped during keyboard navigation.
API
CiderUI.tabs.init()- Scans the document for
[data-tabs]elements and initializes them. Called automatically on DOMContentLoaded andhtmx:afterSettle. CiderUI.tabs.destroy(tabGroupElement)- Tears down event listeners and ARIA attributes for a specific tab group.