a-tabs
An accessible tabs component for organizing content into multiple panels with keyboard navigation and browser search support.
The a-tabs element provides a complete tabs implementation with keyboard navigation, accessibility features, and support for browser find-in-page that automatically reveals hidden content.
Installation
import "@sv/elements/tabs";
Usage
Basic Usage
<a-tabs>
<a-tabs-list label="Main navigation">
<a-tabs-tab>Overview</a-tabs-tab>
<a-tabs-tab>Details</a-tabs-tab>
<a-tabs-tab>Settings</a-tabs-tab>
</a-tabs-list>
<a-tabs-panel>
<h2>Overview</h2>
<p>Overview content goes here</p>
</a-tabs-panel>
<a-tabs-panel>
<h2>Details</h2>
<p>Detailed information goes here</p>
</a-tabs-panel>
<a-tabs-panel>
<h2>Settings</h2>
<p>Settings content goes here</p>
</a-tabs-panel>
</a-tabs>
Preselected Tab
Use the selected attribute to specify which tab should be active initially:
<a-tabs>
<a-tabs-list>
<a-tabs-tab>Tab 1</a-tabs-tab>
<a-tabs-tab selected>Tab 2</a-tabs-tab>
<a-tabs-tab>Tab 3</a-tabs-tab>
</a-tabs-list>
<a-tabs-panel>Panel 1</a-tabs-panel>
<a-tabs-panel>Panel 2</a-tabs-panel>
<a-tabs-panel>Panel 3</a-tabs-panel>
</a-tabs>
With Accessible Label
Provide an aria-label for the tab list to improve accessibility:
<a-tabs>
<a-tabs-list label="Product information tabs">
<a-tabs-tab>Description</a-tabs-tab>
<a-tabs-tab>Specifications</a-tabs-tab>
<a-tabs-tab>Reviews</a-tabs-tab>
</a-tabs-list>
<a-tabs-panel>...</a-tabs-panel>
<a-tabs-panel>...</a-tabs-panel>
<a-tabs-panel>...</a-tabs-panel>
</a-tabs>
Keyboard Navigation
The tabs support full keyboard navigation following WAI-ARIA best practices:
| Key | Action |
|---|---|
ArrowLeft | Move focus to previous tab |
ArrowRight | Move focus to next tab |
Home | Move focus to first tab |
End | Move focus to last tab |
Styling
The tabs elements use minimal styling to allow full customization from outside the shadow DOM:
/* Style the tabs container */
a-tabs {
display: block;
background: white;
border-radius: 8px;
}
/* Style the tab list background */
a-tabs-list {
display: block;
background: #f5f5f5;
border-bottom: 1px solid #e5e5e5;
}
/* Style individual tab buttons */
a-tabs-tab {
padding: 12px 24px;
color: #666;
border-bottom: 2px solid transparent;
transition: all 0.2s;
}
a-tabs-tab:hover {
color: #333;
background: rgba(0, 0, 0, 0.05);
}
/* Style selected tab */
a-tabs-tab[selected] {
color: #0066cc;
border-bottom-color: #0066cc;
font-weight: 600;
}
/* Style the panels */
a-tabs-panel {
display: block;
padding: 24px;
}
Scrollable Tabs
The tabs-list can be optionaly enhanced by importing @sv/elements/track, which will handle scrolling to selected tabs and handle overflow with arrow buttons automatically.
Accessibility
- ARIA Attributes: Automatically manages
role="tab",role="tabpanel",aria-selected,aria-controls, andaria-labelledby. - Keyboard Navigation: Full arrow key navigation with Home/End support.
- Focus Management: Only the selected tab is in the tab order (
tabindex="0"), others havetabindex="-1". - Unique IDs: Automatically generates unique IDs for tab/panel associations.
- Hidden Until Found: Non-selected panels use
hidden="until-found", allowing browser find-in-page to search hidden content and automatically reveal the matching tab. - Hash Navigation: Clicking anchor links within panels automatically selects the correct tab.
Browser Search Support
The tabs use hidden="until-found" which enables modern browsers to search through hidden tab content. When a user uses Ctrl+F (Cmd+F) to search and finds text in a hidden panel:
- The browser fires a
beforematchevent - The corresponding tab automatically becomes selected
- The panel is revealed
- The search result is highlighted
This works in browsers that support the hidden="until-found" feature (Chrome 102+, Edge 102+).
Programmatic Control
const tabs = document.querySelector('a-tabs');
// Select a specific tab by index
tabs.selectTabByIndex(2);
// Navigate tabs programmatically
tabs.selectNextTab();
tabs.selectPreviousTab();
tabs.selectFirstTab();
tabs.selectLastTab();
// Scroll the selected tab into view
tabs.scrollSelectedIntoView();