Design System
Components

Tabs

Underline-style tabs on Radix Tabs — for switching between full views, not disclosure.

A thin styling layer over Radix Tabs: the active tab carries an accent underline. Tabs / TabsList / TabsTrigger / TabsContent compose exactly like the primitive — Radix's own props (value, onValueChange, defaultValue, orientation, etc.) pass through unchanged.

Price Seasons content.

Implementation notes

  • Each TabsContent is a separate view, not a step in a flow. Tabs are for content a user jumps between and back, non-sequentially — a multi-step form or wizard shouldn't be built on top of Tabs.
  • Controlled vs. uncontrolled follows the same rule as everywhere else in the system: pass value/onValueChange when the active tab needs to be driven by the URL or shared state (e.g. a Price Manager tab reflected in ?tab=); use defaultValue for a tab strip with no external state to sync.

Do / Don't

  • Do keep tab labels short and parallel ("Price Seasons", "Price Manager") — a tab strip reads as one set of peers, so wildly different label lengths or phrasing stands out.
  • Don't disable a TabsTrigger to represent "not available yet" without also explaining why somewhere reachable — a silently-disabled tab reads as a bug, the same reasoning that motivates showing permission-gated actions disabled-with-a-reason rather than hidden.

On this page