Tabs
Tab navigation for switching between content panels. Supports underline, pill, and segmented variants.
When to Use
Use Tabs when:
Switching between related views at the same hierarchy level, such as content categories, settings sections, or filter groups. Tabs keep users in context without navigating to a new page.
Don't use when:
The user needs to compare content across tabs simultaneously. For sequential steps, use a stepper. For collapsible content, use Accordion.
Underline (Default)
<?= ws_tabs([
['id' => 'overview', 'label' => 'Overview', 'active' => true],
['id' => 'details', 'label' => 'Details'],
['id' => 'resources', 'label' => 'Resources', 'count' => 5],
]) ?>Pill Variant
<?= ws_tabs($items, ['variant' => 'pill']) ?>
Segmented Variant
<?= ws_tabs($items, ['variant' => 'segmented']) ?>
With Icons & Gating
Tabs can include leading icons, badge counts, gated (locked) states, and disabled states.
<?= ws_tabs([
['id' => 'info', 'label' => 'Info', 'icon' => 'info', 'active' => true],
['id' => 'premium', 'label' => 'Premium', 'icon' => 'star', 'gated' => true],
['id' => 'disabled', 'label' => 'Disabled', 'disabled' => true],
]) ?>Sizes
Small
Medium (default)
Large
Parameters
Tabs Options
| Parameter | Type | Default | Description |
|---|---|---|---|
id | string | auto-generated | Container element ID |
variant | string | underline | underline | pill | segmented |
size | string | md | sm | md | lg |
scrollable | bool | true | Enable horizontal scroll on mobile |
class | string | '' | Additional CSS classes |
Item Options
| Parameter | Type | Default | Description |
|---|---|---|---|
id | string | auto-generated | Tab identifier (used in data-tab) |
label | string | — | Tab label text |
icon | string | null | Material icon name |
count | int | null | Badge count number |
active | bool | false | Initially selected tab |
disabled | bool | false | Disabled state |
gated | bool | false | Shows lock icon (premium gating) |
Anatomy
.ws-tabs — Outer container.ws-tabs__nav — Tab button row (role=tablist).ws-tabs__btn — Individual tab button.ws-tabs__icon — Optional leading icon.ws-tabs__label — Tab label text.ws-tabs__count — Badge count.ws-tabs__lock — Gated lock iconCSS Classes
| Class | Purpose |
|---|---|
.ws-tabs | Base tabs styles |
.ws-tabs--underline | Underline variant (default) |
.ws-tabs--pill | Pill variant |
.ws-tabs--segmented | Segmented variant |
.ws-tabs--sm / --md / --lg | Size modifiers |
.ws-tabs--scrollable | Horizontal scroll on overflow |
.ws-tabs__btn.is-active | Active/selected tab |
.ws-tabs__btn.is-disabled | Disabled tab |
.ws-tabs__btn.is-gated | Gated/locked tab |
Accessibility
The tabs component follows the WAI-ARIA Tabs pattern.
ARIA Attributes
| Element | Attribute | Value |
|---|---|---|
.ws-tabs__nav | role | tablist |
.ws-tabs__btn | role | tab |
.ws-tabs__btn | aria-selected | true | false |
.ws-tabs__btn | aria-controls | ID of associated panel |
.ws-tabs__btn | tabindex | 0 (active) | -1 (inactive) |
.ws-tabs__btn.is-disabled | aria-disabled | true |
| Tab panel | role | tabpanel |
| Tab panel | aria-labelledby | ID of associated tab button |
Keyboard Navigation
| Key | Behavior |
|---|---|
| Tab | Moves focus into the tablist, then to the active tab's panel content |
| ← / → | Moves focus between tabs. Wraps from last to first (and vice versa). Activates the focused tab. |
| Home | Moves focus to the first non-disabled tab |
| End | Moves focus to the last non-disabled tab |
| Enter / Space | Activates the focused tab (if using manual activation mode) |
Implementation Notes
Do:
Disabled tabs receive
aria-disabled="true" and are skipped during arrow key navigation. Gated tabs remain focusable so screen readers can announce the locked state.
Don't:
Don't use
display: none to hide inactive panels — use hidden attribute or aria-hidden so panel content is properly excluded from the accessibility tree while remaining discoverable.
Files
| File | Purpose |
|---|---|
includes/components/helpers.php | ws_tabs() helper function |
includes/components/tabs.php | Tabs template |
includes/components/components.css | Tabs CSS (.ws-tabs rules) |
includes/components/components.js | Tab switching logic |