Basic Example
The component automatically converts headings into tabs with accessible keyboard navigation and ARIA attributes.
Basic Usage
Simply wrap your heading-structured content in the
<tabbed-interface> element.
<tabbed-interface>
<h3>Getting Started</h3>
<p>First tab content.</p>
<h3>Features</h3>
<p>Second tab content.</p>
<h3>Installation</h3>
<p>Third tab content.</p>
</tabbed-interface>
Getting Started
This is the first tab panel. The component automatically creates tabs from headings.
Headers are hidden by default in panels.
Features
- Automatic tab creation from headings
- Full keyboard navigation support
- ARIA attributes for accessibility
- CSS custom properties for styling
Installation
npm install @aarongustafson/tabbed-interface
Then import in your JavaScript:
import '@aarongustafson/tabbed-interface';
Attributes
The component supports several attributes to customize its behavior.
Auto-Activation
Add the auto-activate attribute to make
tabs activate on focus. By default (without the
attribute), tabs require Enter or Space to activate,
following the manual activation pattern for better
accessibility.
<tabbed-interface auto-activate>
<h3>Tab One</h3>
<p>Content here.</p>
<h3>Tab Two</h3>
<p>More content.</p>
</tabbed-interface>
Auto Tab 1
With auto-activation, tabs activate immediately when you focus them with arrow keys.
Auto Tab 2
This can be convenient for quick navigation when you have few tabs.
Auto Tab 3
Just navigate with arrow keys and the panel changes automatically.
Visible Headers
Use show-headers to keep headings visible
in tab panels.
<tabbed-interface show-headers>
<h3>Overview</h3>
<p>Content here.</p>
<h3>Details</h3>
<p>More content.</p>
</tabbed-interface>
Overview
The heading is now visible inside the panel along with the tab.
Details
This can be useful for certain design patterns or when you want redundancy.
Tab List Position
Use tablist-after to place tabs below the
content.
<tabbed-interface tablist-after>
<h3>First</h3>
<p>Content appears above tabs.</p>
<h3>Second</h3>
<p>More content.</p>
</tabbed-interface>
First Section
The tabs appear below the content when using
tablist-after.
Second Section
This can be useful for certain layouts or design patterns.
Default Tab
Use default-tab to set which tab is active
initially (by index or heading ID).
<tabbed-interface default-tab="1">
<h3>Tab 0</h3>
<p>First tab.</p>
<h3>Tab 1</h3>
<p>This tab is active by default.</p>
<h3>Tab 2</h3>
<p>Third tab.</p>
</tabbed-interface>
Tab 0
First tab content.
Tab 1
This tab is active by default because of
default-tab="1".
Tab 2
Third tab content.
Styling Variants
Style the component using CSS
::part() selectors for complete visual control.
Pill-Style Tabs
Create rounded pill-style tabs using
::part() selectors.
tabbed-interface.pills::part(tablist) {
gap: 8px;
margin: 0 0 1em 0;
}
tabbed-interface.pills::part(tab) {
background-color: ButtonFace;
border: none;
border-radius: 999px;
padding: 0.5em 1.5em;
}
tabbed-interface.pills::part(tab):hover {
background-color: SelectedItem;
}
tabbed-interface.pills::part(tab selected),
tabbed-interface.pills::part(tabpanel) {
background-color: Highlight;
color: HighlightText;
}
tabbed-interface.pills::part(tabpanel) {
border: none;
}
Tab One
The pill style is achieved entirely through
CSS ::part() selectors.
Tab Two
No JavaScript changes needed!
Tab Three
Fully customizable appearance.
Minimal Style
A clean, minimal style with an underline indicator.
tabbed-interface.minimal::part(tablist) {
gap: 0;
margin: 0 0 -1px 0;
}
tabbed-interface.minimal::part(tab) {
background: transparent;
border: none;
border-radius: 0;
padding: 0.75em 1em;
}
tabbed-interface.minimal::part(tab):hover {
background: ButtonFace;
}
tabbed-interface.minimal::part(tab selected) {
background: transparent;
color: LinkText;
border-bottom: 2px solid LinkText;
}
tabbed-interface.minimal::part(tabpanel) {
padding: 1.5em 0;
border: none;
border-top: 2px solid AccentColor;
}
Design
A minimal design with just an underline for the active tab.
Develop
Clean and simple, great for modern interfaces.
Deploy
Lightweight visual treatment.
Advanced Features
The component includes several advanced features for enhanced functionality.
Custom Tab Titles
Use data-tab-short-name to show shorter
labels in tabs while keeping full headings in panels.
The full text is available as
aria-label for screen readers.
<tabbed-interface>
<h3 data-tab-short-name="Short">
Very Long Section Title
</h3>
<p>Content here.</p>
<h3 data-tab-short-name="Emoji 🎉">
Plain Heading
</h3>
<p>More content.</p>
</tabbed-interface>
Very Long Section Title That Wouldn't Fit Well In a Tab
The tab shows "Short" but the full heading is visible in the panel and available to screen readers.
Plain Heading
You can even add emoji or other content to your tab titles!
API Reference Guide
Great for abbreviating long titles.
Event Handling
Listen for tabbed-interface:change events
to respond to tab changes.
document.querySelector('tabbed-interface')
.addEventListener(
'tabbed-interface:change',
(event) => {
console.log(event.detail);
}
);
Introduction
Click between tabs and watch the output below.
Details
The event fires whenever the active tab changes and includes useful details.
API
Event detail includes
tabIndex, tabId,
and tabpanelId.
Programmatic Control
Control tabs programmatically using the JavaScript API.
const tabs = document.querySelector(
'tabbed-interface'
);
// Navigate
tabs.next();
tabs.previous();
tabs.first();
tabs.last();
// Set active tab directly
tabs.activeIndex = 2;
Panel A
First panel content with some text.
Panel B
Second panel content with more information.
Panel C
Third panel content with additional details.
Panel D
Fourth panel content to demonstrate navigation.
Hash Navigation
The component supports URL hash navigation for deep linking to specific tabs.
<a href="#features">
Go to Features
</a>
<tabbed-interface>
<h3 id="intro">Introduction</h3>
<p>Content...</p>
<h3 id="features">Features</h3>
<p>Content...</p>
</tabbed-interface>
Jump to Start | Jump to Middle | Jump to End
Start
This tab can be accessed via
#hash-start.
Middle
This tab can be accessed via
#hash-middle.
End
This tab can be accessed via
#hash-end.
Accessibility
The component is built with accessibility as a core feature.
Keyboard Navigation
Full keyboard support following ARIA Authoring Practices.
Arrow Keys Navigate tabs
Home First tab
End Last tab
Enter/Space Activate tab and focus panel content
Tab 1
Use Arrow keys to move between tabs. By default, you must press Enter or Space to activate a tab and view its content.
Tab 2
Press Home to jump to the first tab, or End to jump to the last.
Tab 3
After activating, Enter or Space will move focus to the first focusable element in the panel.
API Reference
For complete documentation of attributes, properties, methods, events, CSS custom properties, keyboard navigation, and browser support, see the README.