Tabs
The .pl-c-tabs component renders a [role="tablist"] of [role="tab"] buttons
that switch between [role="tabpanel"]s. The active state is APP state: set
aria-selected="true" on the tab and [hidden] on inactive panels.
When to use
- Settings pages with grouped sections.
- Dashboards switching between data views.
- Master-detail regions with a small fixed set of tabs.
Semantic HTML
<div class="pl-c-tabs">
<div class="pl-c-tabs__list" role="tablist" aria-label="Sections">
<button
class="pl-c-tabs__tab"
role="tab"
aria-selected="true"
id="tab-overview"
aria-controls="panel-overview"
tabindex="0"
>
Overview
</button>
<button
class="pl-c-tabs__tab"
role="tab"
aria-selected="false"
id="tab-settings"
aria-controls="panel-settings"
tabindex="-1"
>
Settings
</button>
</div>
<div
class="pl-c-tabs__panel"
role="tabpanel"
id="panel-overview"
aria-labelledby="tab-overview"
>
<p>Active panel.</p>
</div>
<div
class="pl-c-tabs__panel"
role="tabpanel"
id="panel-settings"
aria-labelledby="tab-settings"
hidden
>
<p>Hidden panel.</p>
</div>
</div>
Class contract
| Selector | Role |
|---|---|
.pl-c-tabs |
Wrapper - provides grid + gap. |
.pl-c-tabs__list |
The [role="tablist"] container. |
.pl-c-tabs__tab |
A tab button ([role="tab"]). |
.pl-c-tabs__count |
Optional count chip inside a tab. |
.pl-c-tabs__panel |
A panel ([role="tabpanel"]). Inactive ones carry [hidden]. |
Tokens consumed
--pl-color-{accent,surface,surface-2,text,text-muted,border},
--pl-space-{1,2,3}, --pl-text-{xs,sm}, --pl-duration-1, --pl-ease-standard,
--pl-radius-{sm,pill}.
Accessibility
- Keyboard: implement roving tabindex (arrow keys move between tabs,
Home/End jump to first/last). The framework sets
tabindexvalues in the preview; your app must update them on arrow-key navigation. - Focus-visible:
:focus-visibledraws a--pl-focus-colorring. - Selected indicator: box-shadow on the block-end edge (never shifts layout). Selected tab gets accent color + bolder weight.