Tabs with one indicator that slides and resizes between them on a spring: a line under the current tab, a filled pill, or a raised segment on a strip. When the tabs outgrow their space the strip scrolls sideways behind soft fades, arrows appear only while there is more to see, and the current tab always scrolls clear of the edges. Tabs take icons and count badges, follow the WAI-ARIA tabs pattern with automatic or manual activation, and either show panels or render as real links through your own router.
The import and the props worth knowing about, in one place.
import { NavTabs } from "@/components/beste/component/nav-tabs";
// Tabs with panels, controlled
<NavTabs
value={tab}
onValueChange={setTab}
tabs={[
{ value: "overview", label: "Overview", content: <Overview /> },
{ value: "releases", label: "Releases", count: 24, content: <Releases /> },
{ value: "tour", label: "Tour dates", count: 12, content: <Tour /> },
]}
/>
// A segmented strip that selects only on Enter or Space
<NavTabs variant="segment" activation="manual" tabs={tabs} />
// Real links through your router; the strip becomes a labelled nav
<NavTabs
variant="pill"
value={section}
tabs={sections}
getHref={(value) => `/artists/glasper/${value}`}
renderLink={(props) => <Link {...props} />}
aria-label="Artist sections"
/>Every one of these is in the component already. They are listed because a props table cannot mention a gesture, so nothing else on this page can tell you they exist.
| Tab | Move into the strip onto the current tab, then on into its panel. |
|---|---|
| Left / Right | Move to the previous or next tab, wrapping at the ends and skipping disabled ones. |
| Home / End | Move to the first or last tab. |
| Enter / Space | Select the focused tab when activation is manual. |
Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
tabs* | NavTab[] | — | |
value | string | — | Current tab. Pair with `onValueChange` to control it. |
defaultValue | string | the first enabled tab | |
onValueChange | (value: string) => void | — | |
variant | "underline" | "pill" | "segment" | "underline" | |
activation | "automatic" | "manual" | "automatic" | `automatic` selects a tab as the arrow keys reach it; `manual` only moves focus, and Enter or Space selects. |
keepMounted | boolean | — | Keep inactive panels mounted (hidden) instead of unmounting them. |
getHref | (value: string) => string | — | Render tabs as links to these addresses instead of buttons; panels are then left to your routes. |
renderLink | (props: NavTabLinkProps) => React.ReactNode | — | Render the links through your router, e.g. `(props) => <Link {...props} />`. |
tone | "muted" | "outline" | "ghost" | "muted" | |
size | "sm" | "default" | "lg" | "default" | |
disabled | boolean | — | |
panelClassName | string | — | Extra classes for the panel. |
aria-label | string | "Tabs" | |
className | string | — |