Nav Tabs React component for Tailwind CSS v4
v1.0.0Added in 1.0.0
React navigation tabs that are links: the sections of a page or a record change the URL, with the look of tabs and the semantics of navigation.
Click a tab and the URL changes: the indicator glides to it on a smooth spring and the page below swaps. Every tab is a real link in the tab order (middle click opens it in a new tab); with focus on a tab, Left / Right move to the neighbour and Home / End jump to the first and last, Enter follows the link. Too many tabs scroll sideways with soft edge fades and the active one is kept in view, or, with overflow set to menu, the ones that do not fit fold into a More menu that becomes a bottom sheet on a phone. On touch every tab is 44px tall. Sticky tabs stay pinned under the top bar on a glass background while the page scrolls.
Nav Tabs is a Pro React component in the React navigation components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add nav-tabs, together with Badge, Dropdown Menu, Navigation, useControllableState, useOverflowItems and 4 more and the npm packages motion and lucide-react.
Add to a project
Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup
npx wingo-ui@latest add nav-tabsNav Tabs is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans
Usage
Import NavTabs from @/components/ui/nav-tabs.
"use client"
import { usePathname } from "next/navigation"
import Link from "next/link"
import { NavTabs, type NavTabsItem } from "@/components/ui/nav-tabs"
import { LinkProvider } from "@/lib/navigation"
const sections: NavTabsItem[] = [
{ label: "General", href: "/settings/general" },
{ label: "Members", href: "/settings/members", badge: 8 },
{ label: "Billing", href: "/settings/billing" },
{ label: "Integrations", href: "/settings/integrations" },
{ label: "Notifications", href: "/settings/notifications" },
{ label: "Security", href: "/settings/security" },
]
export function SettingsTabs() {
return (
<LinkProvider component={Link} currentPath={usePathname()}>
<NavTabs items={sections} sticky labels={{ navigation: "Company settings" }} />
</LinkProvider>
)
}Props
itemsNavTabsItem[]The tabs (NavItem from lib/navigation): label, href, icon, activeIcon, badge (a number renders a count), disabled, external, match, onSelect. Children are ignored. Items without href render buttons that call onSelect.
valuestringThe active tab's key (id, else href, else the label). Controls the tabs; otherwise the current path decides.
defaultValuestringThe first active tab when no path is known (no LinkProvider, no currentPath). Default: the first enabled item.
onValueChange(key: string, item: NavTabsItem) => voidRuns on every activation, in all three modes (controlled, routed, uncontrolled).
currentPathdefault""stringThe current pathname. Empty: the LinkProvider's. The tab whose href matches it most specifically is active and clicks store nothing. Try /setari/securitate.
variantdefault"underline""underline" | "pill" | "segmented"underline for page sections, pill for lighter filters, segmented for a compact switch. Class for class the tabs looks.
sizedefault"md""sm" | "md" | "lg"32 / 40 / 48px tabs with the matching type and icon size. On touch md grows to 44px and sm keeps its look with a 44px hit area.
tonedefault"neutral""neutral" | "brand" | "success" | "warning" | "danger" | "info"The indicator color: the underline bar, the pill fill or the segmented thumb. Neutral is black in light mode and white in dark mode.
colordefault""stringAny CSS color for the indicator; replaces the tone. Leave empty to use the tone.
radiusdefault"md""none" | "sm" | "md" | "lg" | "full"The pill and segmented shapes, scaled with the size (md is 8 / 10 / 12px). The underline bar is always round.
bordereddefaulttruebooleanUnderline only: the hairline baseline under the whole row.
fullWidthdefaultfalsebooleanTabs share the width equally. The usual choice for two to four segments on a phone.
aligndefault"start""start" | "center"Where the tabs sit when they are narrower than the row.
stickydefaultfalsebooleanSticks to the top of the scrolling area under the top bar (top: var(--topbar-offset, 0px), which the topbar writes) on a glass background.
overflowdefault"scroll""scroll" | "menu"What happens when the tabs do not fit. scroll: the row scrolls sideways with edge fades and keeps the active tab in view. menu: the last tabs fold into a More menu (a bottom sheet on phones); the active tab never folds.
moreLabeldefault"More"stringThe label of the overflow trigger and the accessible title of its bottom sheet on phones.
linkComponent(props: LinkComponentProps) => ReactNodeThe router link for this instance (next/link's Link). Default: the LinkProvider's, else a plain anchor.
labels{ navigation?: string }The nav landmark's accessible name, default "Sections". An aria-label or aria-labelledby on the component wins.
classNamesPartial<Record<"list" | "link" | "indicator" | "badge" | "icon" | "more", string>>Extra classes for the inner parts: the list, every link, the indicator, badge and icon wrappers, the More trigger.
classNamestringExtra classes for the nav root, merged last. Set --bar-bg here when sticky tabs sit on a surface other than the page.
Examples
Variants
Underline, pill and segmented: the tabs looks with link semantics.
More menu
overflow="menu" in a narrow card: tabs that do not fit fold into a menu, a sheet on phones.
Sticky under a top bar
Scroll the frame: the tabs pin under the 56px bar through --topbar-offset.
Icons and live badges
Add a message and the count animates; opening the tab clears it.
Segmented on a phone
fullWidth segmented tabs as a filter at the top of a phone screen.
Custom color
Any CSS color for the underline and the active label.
Dependencies
Files
- components/ui/nav-tabs.tsx
FAQ
Is the React Nav Tabs component free?
The preview, props and docs are free; copying the source needs a Pro plan. See plans.
How do I install Nav Tabs?
Run npx wingo-ui@latest add nav-tabs. It also adds the Wingo UI items it builds on (Badge, Dropdown Menu, Navigation, useControllableState, useOverflowItems and 4 more) and the npm packages motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/nav-tabs.
How does Nav Tabs behave on phones?
Too many tabs scroll sideways with soft edge fades and the active one is kept in view, or, with overflow set to menu, the ones that do not fit fold into a More menu that becomes a bottom sheet on a phone.