Skip to content
HHydro UIdocs
Navigate
ImplementedNavigation / content switching

Tabs

Switch between related panels while keeping one context in view.

Interactive

Try it

value, orientation, activation, loop
ProfileSecurityBillingYour profile details.Security settings.Billing preferences.
Live previewReady
MarkupStateEvents
<hui-tabs id="playground-tabs" value="profile" aria-label="Account settings">
  <hui-tabs-list>
    <hui-tabs-tab value="profile">Profile</hui-tabs-tab>
    <hui-tabs-tab value="security">Security</hui-tabs-tab>
    <hui-tabs-tab value="billing">Billing</hui-tabs-tab>
  </hui-tabs-list>
  <hui-tabs-panel value="profile">Your profile details.</hui-tabs-panel>
  <hui-tabs-panel value="security">Security settings.</hui-tabs-panel>
  <hui-tabs-panel value="billing">Billing preferences.</hui-tabs-panel>
</hui-tabs>
data-state
Waiting for enhancement

No component events yet.

Usage

Use hui-tabs for a set of related panels where one panel is visible at a time. The root value attribute is the selection source of truth. Values are stable strings supplied on each tab and matching panel. The component does not animate or measure panels; consumers may style data-state and data-orientation hooks.

Anatomy

  • Root: hui-tabs
  • List: hui-tabs-list renders a tablist landmark
  • Tab: hui-tabs-tab renders a native button[role="tab"]
  • Panel: hui-tabs-panel renders a tabpanel region
  • State hooks: tabs and panels use data-state="active|inactive"; inactive panels have hidden
  • Orientation hook: the root and list expose data-orientation="horizontal|vertical"

Examples

Fixture exampleSource-backed
<section aria-labelledby="tabs-heading">
    <h2 id="tabs-heading">Account settings</h2>
    <hui-tabs id="account-tabs" value="profile" aria-label="Account settings" loop>
      <hui-tabs-list>
        <hui-tabs-tab value="profile"><b>Profile</b></hui-tabs-tab>
        <hui-tabs-tab value="security">Security</hui-tabs-tab>
        <hui-tabs-tab value="billing" disabled>Billing</hui-tabs-tab>
      </hui-tabs-list>
      <hui-tabs-panel value="profile">Update your profile details.</hui-tabs-panel>
      <hui-tabs-panel value="security">Manage your password and security settings.</hui-tabs-panel>
      <hui-tabs-panel value="billing">Review invoices and payment methods.</hui-tabs-panel>
    </hui-tabs>
  </section>

API reference

Root attributes

AttributeMeaning
valueActive tab value. If omitted, the first enabled tab is selected.
orientationhorizontal (default) or vertical; controls ARIA and arrow-key navigation.
activationautomatic (default) selects while moving focus, or manual selects on Enter/Space/click.
loopAllows arrow-key navigation to wrap from the last tab to the first.
aria-label, aria-labelledby, aria-describedbyNaming and description forwarded to the tab list.

Tab attributes

AttributeMeaning
valueStable value matched by the root and panel.
disabledRemoves the tab from keyboard navigation and prevents selection.
aria-label, aria-labelledby, aria-describedbyOptional accessible naming forwarded to the native tab button.

Panel attributes

AttributeMeaning
valueStable value matching a tab.
aria-label, aria-labelledbyOptional panel naming; generated relationships are added when deterministic IDs exist.

Events:

  • hui-value-change: emitted by the root with { value: string | undefined }.

States and styling

StateContract and styling guidance
Active tabNative tab has aria-selected="true", tabindex="0", and its panel is visible.
Inactive tabNative tab has aria-selected="false", tabindex="-1"; its panel has hidden.
HoverStyle tabs with --hui-color-interactive-hover.
ActiveStyle the selected tab with --hui-color-interactive.
FocusKeep a visible focus ring using --hui-color-focus-ring.
DisabledNative button is disabled and marked aria-disabled="true"; navigation skips it.
State channel

Attributes are the source of truth. Style derived state with data-state, ARIA attributes, and the --hui-* token aliases.

Accessibility and keyboard support

  • Horizontal tabs use ArrowLeft and ArrowRight; vertical tabs use ArrowUp and ArrowDown.
  • In RTL, horizontal arrow meaning is inverted.
  • Home and End focus the first and last enabled tab.
  • Arrow navigation wraps only when loop is present.
  • activation="automatic" selects the focused tab; activation="manual" waits for Enter or Space. Clicking an enabled tab always selects it.
  • Focus remains on the tab after selection. Panels are not focus-trapped.

SSR and forms

SSR emits the complete tablist, tabs, and panels. The selected tab has resolved aria-selected="true"; inactive panels have hidden="hidden"; ARIA relationships use IDs derived from stable root/value attributes or are omitted when no deterministic ID is available. The value attribute is the server seed and is preserved through adoption. Without JavaScript, native tab buttons and the server-selected panel remain usable as a static presentation; consumers may remove hidden to expose every panel.

Code

<hui-tabs id="account-tabs" value="profile" aria-label="Account settings">
  <hui-tabs-list>
    <hui-tabs-tab value="profile">Profile</hui-tabs-tab>
    <hui-tabs-tab value="security">Security</hui-tabs-tab>
  </hui-tabs-list>
  <hui-tabs-panel value="profile">Your profile.</hui-tabs-panel>
  <hui-tabs-panel value="security">Security settings.</hui-tabs-panel>
</hui-tabs>
<hui-tabs id="playground-tabs" value="profile" aria-label="Account settings">
  <hui-tabs-list>
    <hui-tabs-tab value="profile">Profile</hui-tabs-tab>
    <hui-tabs-tab value="security">Security</hui-tabs-tab>
    <hui-tabs-tab value="billing">Billing</hui-tabs-tab>
  </hui-tabs-list>
  <hui-tabs-panel value="profile">Your profile details.</hui-tabs-panel>
  <hui-tabs-panel value="security">Security settings.</hui-tabs-panel>
  <hui-tabs-panel value="billing">Billing preferences.</hui-tabs-panel>
</hui-tabs>