Tabs provide a selection UX, typically used for swapping content shown on a page, or within a navigation context.
<nve-tabs-group id="tab-group-default">
<nve-tabs>
<nve-tabs-item selected command="--toggle" commandfor="tab-group-default" value="overview">Overview</nve-tabs-item>
<nve-tabs-item command="--toggle" commandfor="tab-group-default" value="details">Details</nve-tabs-item>
<nve-tabs-item command="--toggle" commandfor="tab-group-default" value="settings">Settings</nve-tabs-item>
</nve-tabs>
<div slot="overview">overview content</div>
<div slot="details">details content</div>
<div slot="settings">settings content</div>
</nve-tabs-group>
Overview
Details
Settings
overview content
details content
settings content
Installation
<script type="module">
import '@nvidia-elements/core/tabs/define.js';
</script>
<nve-tabs-group id="tab-group-default">
<nve-tabs>
<nve-tabs-item selected command="--toggle" commandfor="tab-group-default" value="overview">Overview</nve-tabs-item>
<nve-tabs-item command="--toggle" commandfor="tab-group-default" value="details">Details</nve-tabs-item>
<nve-tabs-item command="--toggle" commandfor="tab-group-default" value="settings">Settings</nve-tabs-item>
</nve-tabs>
<div slot="overview">overview content</div>
<div slot="details">details content</div>
<div slot="settings">settings content</div>
</nve-tabs-group>
The Tabs component consists of a <nve-tabs> parent element and many <nve-tabs-item> elements slotted as children. The selected attribute when applied to an item by the host application gives the selected tab the proper selected styles.
Apply the disabled attribute to an item to get the proper visual cues and prevent interaction. The elements handle all default interaction, hover, and active states.
Additionally, the component handles all keyboard navigation and accessibility concerns out of the box. Try using left/right arrow keys on horizontal tabs or up/down on vertical tabs.
Borderless Tabs
By default Tabs shows a blue border on the selected item. You can disable the border by setting borderless on the parent <nve-tabs>
Borderless tabs variant for minimal visual styling without border emphasis.
<nve-tabs borderless behavior-select>
<nve-tabs-item selected>Tab 1</nve-tabs-item>
<nve-tabs-item>Tab 2</nve-tabs-item>
<nve-tabs-item>Tab 3 </nve-tabs-item>
<nve-tabs-item disabled>Disabled</nve-tabs-item>
<nve-tabs-item>Tab 5</nve-tabs-item>
</nve-tabs>
Tab 1
Tab 2
Tab 3
Disabled
Tab 5
Border Styles
You can change the border styles by overriding --indicator-background and --indicator-border-radius on <nve-tabs>
Tabs with custom border background styling for brand-specific visual customization.
<nve-tabs
behavior-select
style="--indicator-background: var(--nve-ref-color-brand-green-900); --indicator-border-radius: none"
>
<nve-tabs-item selected> Tab 1 </nve-tabs-item>
<nve-tabs-item> Tab 2 </nve-tabs-item>
<nve-tabs-item> Tab 3 </nve-tabs-item>
</nve-tabs>
Tabs with Dot Indicators
Add dots and icons by simply slotting in <nve-icon> or <nve-dot> into your <nve-tabs-item>
Tabs with notification dots for indicating unread content or alerts within tab sections.
<nve-tabs behavior-select>
<nve-tabs-item>Tab 1</nve-tabs-item>
<nve-tabs-item>Tab 2</nve-tabs-item>
<nve-tabs-item>Tab 3 </nve-tabs-item>
<nve-tabs-item selected>
Tab 4
<nve-dot aria-label="10 notifications">10</nve-dot>
</nve-tabs-item>
<nve-tabs-item>Tab 5</nve-tabs-item>
</nve-tabs>
Tab 1
Tab 2
Tab 3
Tab 4
10
Tab 5
Vertical Tabs
Tabs work as the foundation for a side menu by enabling vertical mode. Simply set vertical on <nve-tabs>
Vertical tabs layout for sidebar navigation and vertical content organization patterns.
<nve-tabs vertical behavior-select style="width: 250px">
<nve-tabs-item selected>Tab 1</nve-tabs-item>
<nve-tabs-item>Tab 2</nve-tabs-item>
<nve-tabs-item>Tab 3</nve-tabs-item>
<nve-tabs-item disabled>Disabled</nve-tabs-item>
<nve-tabs-item>Tab 5</nve-tabs-item>
</nve-tabs>
Tab 1
Tab 2
Tab 3
Disabled
Tab 5
Borderless Vertical Tabs with Icons
This example shows the combination of vertical tabs, set to borderless, with icons slotted.
You can build an Icon only collapsed version of vertical tabs off this system.
Borderless vertical tabs with icons for enhanced visual navigation and minimal styling.
<nve-tabs vertical borderless behavior-select style="width: 250px">
<nve-tabs-item> <nve-icon name="gear"></nve-icon> Tab 1 </nve-tabs-item>
<nve-tabs-item> <nve-icon name="person"></nve-icon> Tab 2 </nve-tabs-item>
<nve-tabs-item selected> <nve-icon name="beaker"></nve-icon> Tab 3 </nve-tabs-item>
<nve-tabs-item> <nve-icon name="add-grid"></nve-icon> Tab 4 </nve-tabs-item>
</nve-tabs>
Stateless Tabs
By default Tabs is stateless. This means the host application must handle selection behavior.
The component provides a way to opt in to stateful selection behavior where click events and keyboard enter trigger the selection state.
All other examples on this page set behavior-select on the parent <nve-tabs> to opt into stateful behavior. The following example
shows the default stateless behavior, where the host app has to set/remove the selected attribute on child <nve-tabs-item>.
Stateless tabs for external state management without built-in selection behavior.
<nve-tabs>
<nve-tabs-item selected>Tab 1</nve-tabs-item>
<nve-tabs-item>Tab 2</nve-tabs-item>
<nve-tabs-item>Tab 3</nve-tabs-item>
<nve-tabs-item>Tab 4</nve-tabs-item>
<nve-tabs-item disabled>Disabled</nve-tabs-item>
</nve-tabs>
Tab 1
Tab 2
Tab 3
Tab 4
Disabled
Links
Tabs with link navigation for routing-based tab switching and page navigation.
<nve-tabs>
<nve-tabs-item selected>
<a href="./docs/elements/tabs/#links">Tab 1</a>
</nve-tabs-item>
<nve-tabs-item>
<a href="./docs/elements/tabs/#links">Tab 2</a>
</nve-tabs-item>
<nve-tabs-item>
<a href="/docs/elements/tabs/#links">Tab 3</a>
</nve-tabs-item>
</nve-tabs>
Grouped Tabs
Use <nve-tabs-group> when a selected tab should also reveal matching panel content. The group keeps selection and panel visibility in sync by matching each tab item value to a named panel slot on the group.
Wrap a single <nve-tabs> in the default slot, add command="--toggle" and commandfor="<group-id>" to each <nve-tabs-item>, and provide panel elements with slot="<value>". Most consumers only need slot, value, command, and commandfor. The group handles the tab panel role and ARIA linkage internally, so consumer markup can stay focused on content.
Do not use behavior-select on <nve-tabs> when the group is present. Let the group coordinate selection.
By default alignment is top, which places the tab strip above the panel region in a column layout.
Group tabs with slot-matched panels and structured card content when one selected value should control both the tab state and revealed details.
<nve-tabs-group id="tab-group">
<nve-tabs>
<nve-tabs-item selected command="--toggle" commandfor="tab-group" value="overview">Overview</nve-tabs-item>
<nve-tabs-item command="--toggle" commandfor="tab-group" value="details">Details</nve-tabs-item>
<nve-tabs-item command="--toggle" commandfor="tab-group" value="settings">Settings</nve-tabs-item>
</nve-tabs>
<div slot="overview">
<nve-card style="width: 100%; min-width: 320px">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Overview</h2>
<p nve-text="body sm muted">High-level release status and current priorities.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">Status</dt>
<dd nve-layout="span:8" nve-text="body">Ready for review</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Audience</dt>
<dd nve-layout="span:8" nve-text="body">Design and product owners</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Next step</dt>
<dd nve-layout="span:8" nve-text="body">Validate the tab labels and panel order</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
<div slot="details">
<nve-card style="width: 100%; min-width: 320px">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Details</h2>
<p nve-text="body sm muted">Supporting context for teams that need implementation specifics.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">Owner</dt>
<dd nve-layout="span:8" nve-text="body">Elements design system</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Coverage</dt>
<dd nve-layout="span:8" nve-text="body">Unit, SSR, and accessibility checks</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Focus</dt>
<dd nve-layout="span:8" nve-text="body">Selection sync and panel wiring</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
<div slot="settings">
<nve-card style="width: 100%; min-width: 320px">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Settings</h2>
<p nve-text="body sm muted">Configuration notes for authors and downstream consumers.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">Selection</dt>
<dd nve-layout="span:8" nve-text="body">Controlled by the active tab value</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Panels</dt>
<dd nve-layout="span:8" nve-text="body">Matched by slot name</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Actions</dt>
<dd nve-layout="span:8" nve-text="body">External buttons can drive the same group</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
</nve-tabs-group>
Overview
Details
Settings
Overview
High-level release status and current priorities.
- Status
- Ready for review
- Audience
- Design and product owners
- Next step
- Validate the tab labels and panel order
Details
Supporting context for teams that need implementation specifics.
- Owner
- Elements design system
- Coverage
- Unit, SSR, and accessibility checks
- Focus
- Selection sync and panel wiring
Settings
Configuration notes for authors and downstream consumers.
- Selection
- Controlled by the active tab value
- Panels
- Matched by slot name
- Actions
- External buttons can drive the same group
Stacked vs Horizontal
Use alignment="start" or alignment="end" on <nve-tabs-group> when you want a vertical tab strip beside the panel region instead of stacked tabs (alignment="top" is the default). start places the tab strip at inline-start; end places it at inline-end (for example, left versus right in LTR). Set vertical on <nve-tabs> and size the tab strip with a width that fits your layout.
Tab group with vertical tab strip at inline-start beside slot-matched panels for sidebar-style settings and details layouts in LTR.
<nve-tabs-group id="tab-group-vertical-start" alignment="start">
<nve-tabs vertical style="width: 250px">
<nve-tabs-item selected command="--toggle" commandfor="tab-group-vertical-start" value="overview"
>Overview</nve-tabs-item
>
<nve-tabs-item command="--toggle" commandfor="tab-group-vertical-start" value="details">Details</nve-tabs-item>
<nve-tabs-item command="--toggle" commandfor="tab-group-vertical-start" value="settings">Settings</nve-tabs-item>
</nve-tabs>
<div slot="overview" style="width: 100%; min-width: 320px">
<nve-card style="width: 100%">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Overview</h2>
<p nve-text="body sm muted">High-level release status and current priorities.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">Status</dt>
<dd nve-layout="span:8" nve-text="body">Ready for review</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Audience</dt>
<dd nve-layout="span:8" nve-text="body">Design and product owners</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Next step</dt>
<dd nve-layout="span:8" nve-text="body">Validate the tab labels and panel order</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
<div slot="details" style="width: 100%; min-width: 320px">
<nve-card style="width: 100%">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Details</h2>
<p nve-text="body sm muted">Supporting context for teams that need implementation specifics.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">Owner</dt>
<dd nve-layout="span:8" nve-text="body">Elements design system</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Coverage</dt>
<dd nve-layout="span:8" nve-text="body">Unit, SSR, and accessibility checks</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Focus</dt>
<dd nve-layout="span:8" nve-text="body">Selection sync and panel wiring</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
<div slot="settings" style="width: 100%; min-width: 320px">
<nve-card style="width: 100%">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Settings</h2>
<p nve-text="body sm muted">Configuration notes for authors and downstream consumers.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">Selection</dt>
<dd nve-layout="span:8" nve-text="body">Controlled by the active tab value</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Panels</dt>
<dd nve-layout="span:8" nve-text="body">Matched by slot name</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Actions</dt>
<dd nve-layout="span:8" nve-text="body">External buttons can drive the same group</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
</nve-tabs-group>
Overview
Details
Settings
Overview
High-level release status and current priorities.
- Status
- Ready for review
- Audience
- Design and product owners
- Next step
- Validate the tab labels and panel order
Details
Supporting context for teams that need implementation specifics.
- Owner
- Elements design system
- Coverage
- Unit, SSR, and accessibility checks
- Focus
- Selection sync and panel wiring
Settings
Configuration notes for authors and downstream consumers.
- Selection
- Controlled by the active tab value
- Panels
- Matched by slot name
- Actions
- External buttons can drive the same group
Tab group with vertical tab strip at inline-end beside slot-matched panels when the tab rail should sit on the opposite side from inline-start sidebars.
<nve-tabs-group id="tab-group-vertical-end" alignment="end">
<nve-tabs vertical style="width: 250px">
<nve-tabs-item selected command="--toggle" commandfor="tab-group-vertical-end" value="overview"
>Overview</nve-tabs-item
>
<nve-tabs-item command="--toggle" commandfor="tab-group-vertical-end" value="details">Details</nve-tabs-item>
<nve-tabs-item command="--toggle" commandfor="tab-group-vertical-end" value="settings">Settings</nve-tabs-item>
</nve-tabs>
<div slot="overview" style="width: 100%; min-width: 320px">
<nve-card style="width: 100%">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Overview</h2>
<p nve-text="body sm muted">High-level release status and current priorities.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">Status</dt>
<dd nve-layout="span:8" nve-text="body">Ready for review</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Audience</dt>
<dd nve-layout="span:8" nve-text="body">Design and product owners</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Next step</dt>
<dd nve-layout="span:8" nve-text="body">Validate the tab labels and panel order</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
<div slot="details" style="width: 100%; min-width: 320px">
<nve-card style="width: 100%">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Details</h2>
<p nve-text="body sm muted">Supporting context for teams that need implementation specifics.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">Owner</dt>
<dd nve-layout="span:8" nve-text="body">Elements design system</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Coverage</dt>
<dd nve-layout="span:8" nve-text="body">Unit, SSR, and accessibility checks</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Focus</dt>
<dd nve-layout="span:8" nve-text="body">Selection sync and panel wiring</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
<div slot="settings" style="width: 100%; min-width: 320px">
<nve-card style="width: 100%">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Settings</h2>
<p nve-text="body sm muted">Configuration notes for authors and downstream consumers.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">Selection</dt>
<dd nve-layout="span:8" nve-text="body">Controlled by the active tab value</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Panels</dt>
<dd nve-layout="span:8" nve-text="body">Matched by slot name</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Actions</dt>
<dd nve-layout="span:8" nve-text="body">External buttons can drive the same group</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
</nve-tabs-group>
Overview
Details
Settings
Overview
High-level release status and current priorities.
- Status
- Ready for review
- Audience
- Design and product owners
- Next step
- Validate the tab labels and panel order
Details
Supporting context for teams that need implementation specifics.
- Owner
- Elements design system
- Coverage
- Unit, SSR, and accessibility checks
- Focus
- Selection sync and panel wiring
Settings
Configuration notes for authors and downstream consumers.
- Selection
- Controlled by the active tab value
- Panels
- Matched by slot name
- Actions
- External buttons can drive the same group
External Controls
<nve-tabs-group> also accepts external invokers such as <nve-button> as long as they target the group with commandfor and provide a matching value. This works well when secondary controls elsewhere on the page should reveal the same tab panel content.
Drive the same tabs group from external buttons when layouts need tabs and secondary actions to stay in sync with structured panel content.
<div nve-layout="column gap:lg">
<nve-tabs-group id="tab-group-controls">
<nve-tabs>
<nve-tabs-item selected command="--toggle" commandfor="tab-group-controls" value="overview"
>Overview</nve-tabs-item
>
<nve-tabs-item command="--toggle" commandfor="tab-group-controls" value="details">Details</nve-tabs-item>
<nve-tabs-item command="--toggle" commandfor="tab-group-controls" value="settings">Settings</nve-tabs-item>
</nve-tabs>
<div slot="overview">
<nve-card style="width: 100%; min-width: 320px">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Overview</h2>
<p nve-text="body sm muted">Quick status for the current tab group.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">State</dt>
<dd nve-layout="span:8" nve-text="body">Overview is active</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Signal</dt>
<dd nve-layout="span:8" nve-text="body">Use this tab for a summary of the current workflow</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Tip</dt>
<dd nve-layout="span:8" nve-text="body">Pair it with external controls for quick switching</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
<div slot="details">
<nve-card style="width: 100%; min-width: 320px">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Details</h2>
<p nve-text="body sm muted">Deeper context for follow-up tasks and implementation notes.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">State</dt>
<dd nve-layout="span:8" nve-text="body">Details are available on demand</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Signal</dt>
<dd nve-layout="span:8" nve-text="body">Use this tab when readers need extra context</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Tip</dt>
<dd nve-layout="span:8" nve-text="body">Keep the content specific to the selected tab</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
<div slot="settings">
<nve-card style="width: 100%; min-width: 320px">
<nve-card-header>
<div nve-layout="column gap:xs">
<h2 nve-text="heading sm bold">Settings</h2>
<p nve-text="body sm muted">Preferences and coordination notes for the shared tab group.</p>
</div>
</nve-card-header>
<nve-card-content>
<dl nve-layout="grid gap:sm">
<dt nve-layout="span:4" nve-text="body muted medium">State</dt>
<dd nve-layout="span:8" nve-text="body">Settings remain in sync with the selected value</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Signal</dt>
<dd nve-layout="span:8" nve-text="body">Useful for configuration and admin actions</dd>
<dt nve-layout="span:4" nve-text="body muted medium">Tip</dt>
<dd nve-layout="span:8" nve-text="body">Use external buttons when the layout needs extra actions</dd>
</dl>
</nve-card-content>
</nve-card>
</div>
</nve-tabs-group>
<div nve-layout="row gap:xs">
<nve-button command="--toggle" commandfor="tab-group-controls" value="overview">overview</nve-button>
<nve-button command="--toggle" commandfor="tab-group-controls" value="details">details</nve-button>
<nve-button command="--toggle" commandfor="tab-group-controls" value="settings">settings</nve-button>
</div>
</div>
Overview
Details
Settings
Overview
Quick status for the current tab group.
- State
- Overview is active
- Signal
- Use this tab for a summary of the current workflow
- Tip
- Pair it with external controls for quick switching
Details
Deeper context for follow-up tasks and implementation notes.
- State
- Details are available on demand
- Signal
- Use this tab when readers need extra context
- Tip
- Keep the content specific to the selected tab
Settings
Preferences and coordination notes for the shared tab group.
- State
- Settings remain in sync with the selected value
- Signal
- Useful for configuration and admin actions
- Tip
- Use external buttons when the layout needs extra actions
overview
details
settings
Release Status
All elements and features go through 3 phases of stability, pre-release, beta and stable.
pre-release
Docs Preview
API Documentation
Fully Themeable
beta
Robust unit test coverages
Passed API Review
Passed Designer VQA Review
Included in library package
stable
No known outstanding AA WCAG issues
No known outstanding performance issues
Adapts to different screen/container sizes
No breaking API changes for at least 90 days