tab-set

Tabbed content panels with keyboard navigation and ARIA semantics.

Overview

The <tab-set> component transforms a group of <details> elements into a tab interface. Without JavaScript, it works as an accordion. With JavaScript, it adds keyboard navigation and ARIA linkage attributes while preserving native <details>/<summary> semantics.

Attributes

AttributeValuesDefaultDescription
aria-labelstringAccessible label for the tab group
transition"fade", "slide", "scale"View Transition animation between tab panels

Required Structure

ElementRequiredDescription
<details>yesOne per tab — native disclosure element provides open/close state
<summary>yesTab label inside each <details>

Child Details Attributes

Attribute Type Description
name string Shared name for exclusive behavior. All tabs should have the same name.
open boolean Initially selected tab. If none specified, first tab is selected.

Progressive Enhancement

The component is built on the native <details> element, which provides built-in expand/collapse functionality. The shared name attribute (supported in modern browsers) ensures only one panel is open at a time.

Without JavaScript

When JavaScript is disabled or fails to load, the tabs degrade gracefully to an accordion-style interface where each panel can be expanded independently.

With JavaScript

  • Native <details>/<summary> semantics are preserved (no role overrides)
  • aria-controls and aria-labelledby link each tab to its panel
  • aria-selected state is managed on each summary
  • tabindex is managed for roving focus
  • Keyboard navigation (arrow keys, Home, End) is enabled

Keyboard Navigation

When focused on a tab, the following keyboard shortcuts are available:

Key Action
ArrowRight Move to and activate the next tab
ArrowLeft Move to and activate the previous tab
Home Move to and activate the first tab
End Move to and activate the last tab

Try using arrow keys to navigate between tabs:

First

Press ArrowRight to move to the next tab.

Second

Press ArrowLeft to move to the previous tab, or End to jump to the last.

Third

Press Home to jump back to the first tab.

Rich Tab Content

Tabs can contain any HTML content, including forms, images, and other components.

Text Content

Tabs can contain rich text content with proper typography.

Including blockquotes, lists, and other typographic elements.
Form Content
Card Grid
Card 1 Card 2 Card 3

Events

The component dispatches a custom event when a tab is changed.

Event Detail Description
tab-set:change { index: number } Fired when a tab is activated. index is the 0-based tab index.

Accessibility

Native Semantics

The component preserves native <details>/<summary> semantics. It does not override roles with role="tablist", role="tab", or role="tabpanel". Instead, it layers ARIA linkage attributes on top of the native elements:

  • aria-controls on each <summary> points to its panel
  • aria-labelledby on each panel points back to its summary
  • aria-selected reflects which tab is currently active
  • tabindex is managed via the roving tabindex pattern (active tab gets 0, others get -1)

Screen Reader Behavior

Screen readers will recognize the native disclosure widgets and allow users to navigate between tabs using the roving tabindex pattern.

JavaScript API

The component manages its state internally but you can programmatically control tabs by manipulating the underlying <details> elements.

View Transitions

Add transition to enable animated tab switches using the View Transitions API. Three animation types are available:

ValueEffect
fade (default)Crossfade between panels
slideDirectional slide — forward when moving right, backward when moving left
scaleScale down old panel, scale up new panel
Design

Slides forward to the next tab, backward to previous.

Build

Direction is computed automatically from tab index.

Ship

Works with both mouse clicks and keyboard navigation.

Styling

The tabs component can be styled using CSS. The component adds ARIA attributes that can be used for styling.