tabs-wc

Tabbed content panels with keyboard navigation and ARIA semantics.

Overview

The <tabs-wc> 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 tab semantics.

<tabs-wc aria-label="Feature tabs"> <details name="feature-tabs" open> <summary>Overview</summary> <div>Content for Overview tab</div> </details> <details name="feature-tabs"> <summary>Features</summary> <div>Content for Features tab</div> </details> <details name="feature-tabs"> <summary>Usage</summary> <div>Content for Usage tab</div> </details> </tabs-wc>

Attributes

Attribute Type Default Description
aria-label string - Accessible label for the tab list (required for accessibility).
data-transition string fade Enable View Transition animations when switching tabs. Values: fade, slide, scale.

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

  • ARIA role="tablist", role="tab", and role="tabpanel" are applied
  • Keyboard navigation is enabled
  • aria-selected state is managed
  • Focus management is handled

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
tabs-wc:change { index: number } Fired when a tab is activated. index is the 0-based tab index.
<script> const tabs = document.querySelector('tabs-wc'); tabs.addEventListener('tabs-wc:change', (event) => { console.log('Tab changed to:', event.detail.index); }); </script>

Accessibility

ARIA Roles

The component automatically applies the following ARIA roles:

  • role="tablist" on the <tabs-wc> element
  • role="tab" on each <summary> element
  • role="tabpanel" on each panel content element

ARIA States

  • aria-selected indicates the active tab
  • aria-controls links tabs to their panels
  • aria-labelledby links panels back to their tabs
  • tabindex is managed for proper focus order

Screen Reader Behavior

Screen readers will announce the tab interface and allow users to navigate between tabs using the roving tabindex pattern.

<!-- Always include an aria-label on tabs-wc --> <tabs-wc aria-label="Product information"> ... </tabs-wc>

JavaScript API

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

const tabs = document.querySelector('tabs-wc'); // Get all tab panels const panels = tabs.querySelectorAll('details'); // Programmatically open a tab panels[1].open = true; // Opens the second tab // Check which tab is open const openIndex = [...panels].findIndex(p => p.open); console.log('Open tab index:', openIndex); // Listen for changes tabs.addEventListener('tabs-wc:change', (e) => { console.log('New tab:', e.detail.index); });

View Transitions

Add data-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.

<tabs-wc data-transition="slide" aria-label="Feature tour"> <details name="tour" open> <summary>Design</summary> <div><p>Slides forward to the next tab, backward to previous.</p></div> </details> <details name="tour"> <summary>Build</summary> <div><p>Direction is computed automatically from tab index.</p></div> </details> <details name="tour"> <summary>Ship</summary> <div><p>Works with both mouse clicks and keyboard navigation.</p></div> </details> </tabs-wc>

Styling

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

/* Style the tab list */ tabs-wc { display: block; } /* Style individual tabs */ tabs-wc summary { /* Tab styling */ } /* Active tab */ tabs-wc summary[aria-selected="true"] { border-color: var(--color-interactive); } /* Tab panels */ tabs-wc details > div { padding: var(--size-m); }