HyTabNav
Usage examples on this page are written for Lit / plain HTML (
<hy-tab-nav>). The same component ships asHyTabNavin@whitespaceux/harmony-react(native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.
Link navigation that looks like tabs: a <nav> landmark of hy-tab-nav-item links, one URL each.
Use it for secondary navigation between pages (a settings section switcher, a top strip that changes the route): the back button works, each item is a link, and the current item carries aria-current="page". hy-tab-group is the in-place counterpart (role="tablist", panels switch without a URL change); hy-toggle-group is a value picker. Pick by one question — does the URL change?
Tabs vs tab nav vs toggle group
| In place (no URL) | Navigates (URL) | |
|---|---|---|
| Tab-shaped | hy-tab-group / hy-tab | hy-tab-nav / hy-tab-nav-item |
| Value picker | hy-toggle-group | — |
Industry precedent for keeping the two lookalikes apart: Radix Themes Tabs vs TabNav, Primer UnderlinePanels vs UnderlineNav, GOV.UK secondary navigation. There is no role="tablist", no aria-selected and no roving tabindex here — these are links, and Tab moves between them.
What it syncs
emphasis, size and orientation are pushed down to every child item on first render, on prop change and whenever the slotted items change, exactly like hy-tab-group does for its tabs. The chrome is pixel-identical to hy-tab at every rung, so a tab strip and a link strip sitting side by side read as one family.
Narrow regions
By default the items stay on one row, exactly like hy-tab-group. In a region that can get narrow (a resizable rail), set wrap: the item list wraps onto further rows while the action regions stay pinned at the trailing edge of the first row and never shrink — the collapse control is the last thing to go, not the first. Links wrap; tabs don't (GOV.UK service navigation, Bootstrap pills).
Actions
The actions-start / actions-end slots host controls that apply to the whole strip (a collapse button, a global search). They render beside the item list — never inside it — and each region auto-promotes to role="toolbar" when it holds 2 or more controls; name it with actions-start-label / actions-end-label.
Examples
Section switcher (soft pills)
<hy-tab-nav label="Settings section" emphasis="soft" size="small">
<hy-tab-nav-item href="/settings/primitives" active>Primitives</hy-tab-nav-item>
<hy-tab-nav-item href="/settings/semantics">Semantics</hy-tab-nav-item>
<hy-tab-nav-item href="/settings/components">Components</hy-tab-nav-item>
<hy-icon-button slot="actions-end" name="arrow-collapse" label="Hide navigation"></hy-icon-button>
</hy-tab-nav>Underline strip (the default plain emphasis)
<hy-tab-nav label="Project">
<hy-tab-nav-item href="/overview" active>Overview</hy-tab-nav-item>
<hy-tab-nav-item href="/activity">Activity</hy-tab-nav-item>
<hy-tab-nav-item href="/settings">Settings</hy-tab-nav-item>
</hy-tab-nav>Vertical
<hy-tab-nav label="Account" orientation="vertical">
<hy-tab-nav-item href="/account/profile" active>Profile</hy-tab-nav-item>
<hy-tab-nav-item href="/account/security">Security</hy-tab-nav-item>
<hy-tab-nav-item href="/account/billing">Billing</hy-tab-nav-item>
</hy-tab-nav>Client-side routing
<hy-tab-nav label="Project" id="project-nav">
<hy-tab-nav-item value="overview" href="/overview" active>Overview</hy-tab-nav-item>
<hy-tab-nav-item value="activity" href="/activity">Activity</hy-tab-nav-item>
</hy-tab-nav>
<script>
document.getElementById('project-nav').addEventListener('activate', (e) => {
e.detail.originalEvent.preventDefault(); // stop the full-page navigation
router.push(e.detail.href);
});
</script>API
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
label | label | string | '' | Accessible name of the <nav> landmark — required. A page usually has several navigation landmarks, and the name is how a screen-reader user tells them apart. Dev mode warns when it is empty. |
orientation | orientation | 'horizontal' | 'vertical' | 'horizontal' | Layout axis propagated to every child item. - horizontal (default) — a row, indicator on the block-end edge - vertical — a column, indicator on the inline-start edge |
emphasis | emphasis | 'solid' | 'soft' | 'outlined' | 'plain' | 'plain' | Visual chrome weight propagated to every child item. - plain (default) — transparent rest, role underline indicator - soft — role-tinted rounded rectangle on the current item - outlined — boxed/bordered items - solid — fully filled current item |
size | size | 'small' | 'medium' | 'large' | 'medium' | Type + padding rung propagated to every child item. - small — label-md type on row-nav-md padding - medium (default) — body-md type on row-nav-lg padding - large — body-lg type on row-nav-lg padding |
wrap | wrap | boolean | false | Lets the item list wrap onto further rows when the region is too narrow for one row. The action regions stay at the trailing edge, centered on the list block, and never shrink. Off by default so the strip stays a pixel lookalike of hy-tab-group, which keeps one row. |
actionsStartLabel | actions-start-label | string | '' | Accessible name applied as aria-label to the leading actions region when it auto-promotes to role="toolbar" (2+ controls). |
actionsEndLabel | actions-end-label | string | '' | Accessible name for the trailing actions region when it auto-promotes to role="toolbar". |
Slots
| Slot | Description |
|---|---|
default | The hy-tab-nav-item elements. |
actions-start | Strip-wide controls rendered at the leading edge, beside the item list. Auto-promotes to role="toolbar" with 2+ controls. |
actions-end | Strip-wide controls rendered at the trailing edge. Auto-promotes to role="toolbar" with 2+ controls. |
CSS Parts
| Part | Description |
|---|---|
base | The <nav> landmark. |
list | The container wrapping the items. |
actions-start | The leading actions region. |
actions-end | The trailing actions region. |
CSS Custom Properties
| Property | Description |
|---|---|
--hy-tab-nav-gap | Gap between items. Default: none in a row (items touch, as in hy-tab-group), var(--hy-gap-layout-2xs) in a column. |
--hy-tab-nav-actions-gap | Gap between the item list and the action regions, and between controls within a region. Default: var(--hy-gap-layout-sm). |