Components / Nav Tabs

Nav Tabs

Route-linked sub-navigation across an area’s pages (Social → Live Posts / Schedule / Accounts). For in-place view switching inside one surface, use Tabs instead.

import { NavTabs, NavTab, OverflowNavTabs } from '@layers/ui/nav-tabs'

Rendered stock

House rules

  • Router-agnostic: pass the app’s link element via render (web-v2 binds TanStack Link in components/app/nav-tabs.tsx) and drive active from the location.
  • OverflowNavTabs is the routed area row: it measures the live container and collapses non-fitting tabs into a "More" menu; the first tab is pinned, and an overflowed active tab is promoted to the second slot.
  • activeKey has THREE states: a key lights that tab, null lights NOTHING, and omitting it falls back to the first tab. Pass null — never undefined — from an app that has already decided no tab owns the URL, or the row underlines the first tab and answers "where am I" with somewhere the reader is not.
  • Tab labels are the mono uppercase recipe (built in); never restyle the row’s type or spacing per surface.
  • NavTabs (the dumb container) is for non-navigational tab buttons, e.g. the marketing demo.
  • badge pins a live count after the label (a pending-work queue, unread items). Omit it — never pass 0 — when there is nothing to report; it renders on the visible tab, in the "More" menu, and counts toward overflow measurement.
  • badgeTone="warning" is for a count the user must ACT on (broken connections, failed items) rather than a queue depth they are tracking — it takes the status tokens, not a hand-picked amber. Default stays neutral: a tab that shouts for an ordinary count is one nobody reads twice.
  • The underline tab style is NavTabs’ alone — the segmented Tabs component has no line/underline variant, so an underline always means NavTabs.
  • menu turns a tab into a GROUP: it opens the routes it holds instead of navigating itself, and the app keeps it lit for every one of them via activeKey. This is how an area collapses many peer sections behind one tab WITHOUT a second routed row — the two-tier row is not an approved layout, and the compact shell has no room for one. Mark the open route with current so the menu answers "where am I".
  • A group tab omits renderLink (it has nothing of its own to navigate to). Its routes carry real link elements, so cmd-click and copy-link keep working; a group that overflows flattens its routes under its name inside "More" rather than nesting a submenu in a row that already ran out of width.

See also