OGANIKO DESIGN SYSTEM

Tabs os-002

Also known as: Tab bar, Tab group, Segmented control

Switch between related content sections.

Example
underline (default)
Primary blue #3b82f6, indigo #a5b4fc, violet #ddd6fe. Five gradient stops create the aurora colour field.
Variants
underline
header-nav (dark)
The accent bar runs under the whole row but breaks under the active tab, so the selected tab connects seamlessly into the page below.
pill
cell
underline-animated
segmented
How it works
One tab is active at a time. Clicking a tab shows its panel and hides the others. The active tab is visually distinguished — underline variant uses a bottom border accent, pill variant uses a filled background. Keyboard accessible: arrow keys move between tabs, Enter/Space activates. The header-nav (dark) variant is the navigation form of the same pattern: real page links (<a> inside <nav>) instead of buttons and panels, styled for a dark header. Its signature: a 3px accent bar under the full tab row that breaks under the active tab (a same-colour box-shadow from the active tab covers the bar), so the selected tab merges into the page. The active link carries aria-current="page". Keep the header block identical across the pages it links, so content doesn't jump on tab switch. Three variants assimilated from 21st.dev (packaged as packages/og-tabs.css): cell renders tabs as joined bordered cells (icon-friendly, 2px accent bar under the active cell); underline-animated adds a sliding accent indicator (an absolutely-positioned bar that transitions width/translate to the active tab — needs the small positioning script from packages/og-tabs.html); segmented is the pill pattern refined: muted container, active tab raised on a white card with a soft shadow. All three respect prefers-reduced-motion.
Relationships
None — standalone component. Commonly used inside cards, settings panels, and design system pages.
Parameters
NameTypeDefaultDescription
itemsarray—Tab items: {label, content}
defaultIndexnumber0Initially active tab
variantstringunderlineunderline | pill | header-nav-dark (as <nav> of links) | cell | underline-animated | segmented
onChangefunction—Callback when active tab changes
classNamestring""Additional CSS classes
Tokens
--color-text --color-text-secondary --color-border-subtle --color-bg --color-bg-secondary --text-sm --weight-medium --spacing-3 --spacing-5 --color-accent --color-text-inverse --color-text-inverse-muted --color-bg-inverse-hover --weight-bold --radius-md --spacing-1 --color-text-muted --color-bg-muted --color-border --color-border-focus --shadow-sm --radius-sm --spacing-2 --transition-fast --transition-base
Provenance
VariantProven inLive atDate
header-nav-darkOG-030-Ioioio-Design-Review (client report hub)oganiko.com/digital/clients/ioioio/2026-07-04
cell21st.dev — @k3menn "Tabs in cell for navigation" (external assimilation)21st.dev2026-08-08
underline-animated21st.dev — @coss.com "Tabs" (external assimilation)21st.dev2026-08-08
segmented21st.dev — @originui "Tabs" (external assimilation)21st.dev2026-08-08
header-nav-dark survived a client-facing presentation pass: equal header heights across pages, accent bar broken under the active tab (Phil-approved tab language). The three 21st.dev variants were translated from React/Tailwind to tokenized vanilla CSS (ODS-Components bookmark collection); no license declared on the source listings — re-check before redistributable use.
Code
os-002 · Source: components/Tabs.jsx ▾
<Tabs
  items={[
    { label: 'Colour Stops', content: <ColourStopsPanel /> },
    { label: 'Opacity', content: <OpacityPanel /> },
    { label: 'Animation', content: <AnimationPanel /> },
  ]}
  defaultIndex={0}
  variant="underline"
/>