Container component that manages a set of tabs and their associated panels, providing keyboard navigation and ARIA tab pattern support.
Full ARIA support with proper roles and states. Focus management follows the ARIA tabs pattern. Disabled tabs are properly announced to screen readers.
Keyboard Navigation
Horizontal (top/bottom position):
- Arrow Left/Right or h/l: Navigate between tabs
- Home/End: Jump to first/last tab
Vertical (start/end position):
- Arrow Up/Down or j/k: Navigate between tabs
- Home/End: Jump to first/last tab
Basic Usage
Code
<m-tab-list label="Example">
<m-tab panel="tab1">Tab 1</m-tab>
<m-tab panel="tab2">Tab 2</m-tab>
<m-tab-panel name="tab1">Panel 1</m-tab-panel>
<m-tab-panel name="tab2">Panel 2</m-tab-panel>
</m-tab-list> Bottom Position
Code
<m-tab-list label="Example" position="bottom">
<m-tab panel="tab1">Tab 1</m-tab>
<m-tab panel="tab2">Tab 2</m-tab>
<m-tab-panel name="tab1">Panel 1</m-tab-panel>
<m-tab-panel name="tab2">Panel 2</m-tab-panel>
</m-tab-list> Vertical Layout
Code
<m-tab-list label="Example" position="start">
<m-tab panel="tab1">Tab 1</m-tab>
<m-tab panel="tab2">Tab 2</m-tab>
<m-tab-panel name="tab1">Panel 1</m-tab-panel>
<m-tab-panel name="tab2">Panel 2</m-tab-panel>
</m-tab-list> Disabled Tabs
Code
<m-tab-list label="Example">
<m-tab panel="tab1">Tab 1</m-tab>
<m-tab panel="tab2" disabled>Tab 2 (Disabled)</m-tab>
<m-tab panel="tab3">Tab 3</m-tab>
<m-tab-panel name="tab1">Panel 1</m-tab-panel>
<m-tab-panel name="tab2">Panel 2</m-tab-panel>
<m-tab-panel name="tab3">Panel 3</m-tab-panel>
</m-tab-list> Terminal Wipe
Code
<m-tab-list label="Example" transition="terminal-wipe">
<m-tab panel="tab1">Tab 1</m-tab>
<m-tab panel="tab2">Tab 2</m-tab>
<m-tab panel="tab3">Tab 3</m-tab>
<m-tab-panel name="tab1">Panel 1 — switch tabs to see the wipe</m-tab-panel>
<m-tab-panel name="tab2">Panel 2 content</m-tab-panel>
<m-tab-panel name="tab3">Panel 3 content</m-tab-panel>
</m-tab-list> Event Listening
Listen to m-tab-show and m-tab-hide events to react to tab changes.
Switch tabs to see events...
Code
<div class="stack" data-gap="2">
<m-tab-list id="event-tabs" label="Event Example">
<m-tab panel="tab1">Tab 1</m-tab>
<m-tab panel="tab2">Tab 2</m-tab>
<m-tab panel="tab3">Tab 3</m-tab>
<m-tab-panel name="tab1">Panel 1</m-tab-panel>
<m-tab-panel name="tab2">Panel 2</m-tab-panel>
<m-tab-panel name="tab3">Panel 3</m-tab-panel>
</m-tab-list>
<div id="tab-event-output" class="box" style="padding: var(--size-2); background: var(--color-surface-raised); min-height: 3rem;">
Switch tabs to see events...
</div>
</div>
<script>
const eventTabs = document.getElementById('event-tabs');
const tabEventOutput = document.getElementById('tab-event-output');
eventTabs.addEventListener('m-tab-show', (e) => {
tabEventOutput.textContent = `Tab shown: ${e.detail.tab.textContent} → Panel: ${e.detail.panel.name}`;
});
eventTabs.addEventListener('m-tab-hide', (e) => {
console.log('Tab hidden:', e.detail.tab.textContent);
});
</script> - label string ''
- Accessible label for the tab list
- tab string ''
- The currently active tab panel name
- position "top"|"bottom"|"start"|"end" 'top'
- Tab list orientation
- transition "none"|"terminal-wipe" 'none'
- Panel entry transition style
- adoptedStyleSheets array [baseStyleSheet]
- render void
- m-tab-show CustomEvent
- Fired when a tab panel becomes visible. Detail: MTabChangeEventDetail { tab: MTab, panel: MTabPanel }
- m-tab-hide CustomEvent
- Fired when a tab panel becomes hidden. Detail: MTabChangeEventDetail { tab: MTab, panel: MTabPanel }
- tab
- Slot for m-tab elements (auto-assigned)
- tab-panel
- Slot for m-tab-panel elements (auto-assigned)
- ::part(tab)
- Container wrapping the tab buttons