Standard
The default strip. Reach for it when the choices are few, short, and equal in weight, and you want the current one to read at a glance.
Every request, unfiltered. Start here when you are scanning for anything that needs attention.
Built-in Features
Activates on any switcher in the page. No setup call, no configuration object.
Picking a segment reveals its panel and hides the rest, and fires an event you can listen for.
Arrow keys walk the strip, Home and End jump to the ends, Enter or Space commits the choice.
32, 40, and 48px strips, with label size, inline padding, and corner radius all following the step.
The current segment turns brand green on dark backgrounds, in dark mode automatically or in light mode with one class.
Rounded ends, seams, and arrow-key direction all mirror with text direction. No extra markup.
Labels render as animated bars while data is in flight, and before the component's own script arrives.
Read or change the current segment from script, and re-scan the page after injecting new markup.
Usage Guidelines
Best Practices
- Use a content switcher for two to four short, equal-weight views of the same subject: a date range, a status filter, a chart granularity
- Use it when the current choice must stay obvious at a glance. The solid fill reads faster than an underline across a dense page
- Do not use it for page-level navigation between unrelated areas. Use Tabs, which handle longer labels, icons, vertical layouts, and overflow scrolling
- Do not use it as a form input. Segments are tabs, not controls: no
name, novalue, nothing submitted. For a bounded choice inside a form use Radio, which looks different but is the only NDS control that submits a single choice - Do not use it as a toolbar of actions. Segments select a view, they do not run commands. Use a plain Button group for that
- Keep labels to one or two words. The strip does not scroll, so long labels either crowd the row or push it past its container
- Keep the segment count stable. A strip whose options come and go is a filter, not a switcher
- Pick the size from the surrounding density:
nds-sminside cards and toolbars, the default in page content,nds-lgfor touch-first layouts - Mark the starting segment in your HTML with
aria-selected="true"and give its panel nohiddenattribute, so the correct view paints before scripts run - Every segment needs a panel. A switcher with no panels does not initialize; for a panel-free view toggle use a button group and handle clicks yourself
Modifier Classes
| Class | Description |
|---|---|
nds-content-switcher | Co-class on the .nds-tabs root. Turns the tab strip into a segmented control |
nds-center | On .nds-tab-list. Centers the strip in its row instead of aligning it to the inline start |
nds-oncolor | On the root. Applies the dark-surface palette in light mode, for a strip placed on a dark or brand-filled panel |
nds-sm | On the root. 32px segments with the small type step and a tighter corner radius |
nds-lg | On the root. 48px segments. The unmodified default is 40px, so the middle step needs no class |
nds-loading | On the root or the strip. Renders labels as animated bars. Equivalent to data-state="loading" |
Data Attributes
| Attribute | Description |
|---|---|
aria-selected="true" | Set on one segment to mark the starting choice. Its panel must not carry hidden. Every other segment takes aria-selected="false" and tabindex="-1", and its panel takes hidden |
aria-controls | Set on each segment to the id of its panel. Panels pair back with aria-labelledby |
data-state="loading" | Set on the root or the strip to show the skeleton while data loads. Equivalent to the nds-loading class |
data-nds-tabs-initialized | Stamped on the root by JS once wired. Until it lands the skeleton paints, so the strip is never bare |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--btn-group-radius | var(--radius-md) | Corner radius of the strip's outer ends. Set on .nds-tab-list. Drops to var(--radius-sm) at nds-sm |
--btn-size | 40px | Segment height. Set on .nds-tab for a size between the three steps |
--tab-button-padding-inline | the button's own padding | Horizontal padding inside each segment. Tracks the size step unless you override it |
--tab-panel-padding | var(--spacing-2xl) | Padding around panel content. Axial --tab-panel-padding-inline and --tab-panel-padding-block override one side each |
JavaScript API
The switcher is driven by NDS.Tabs, the same controller behind Tabs. It wires itself on page load. Call NDS.Tabs.reinit() after injecting a switcher into the page.