@ai-created/ui
All components

Fields & selection

Tabs / useTabPanelProps

A controlled, keyboard-navigable tablist for switching between peer panels in place.

TabsTabsPropsTabuseTabPanelProps
View source

Component workbench

Configure the production component, inspect it at responsive widths, copy synchronized JSX, and share the exact state from one workspace.

Overview keeps the essential project context in one place.

Anatomy

Named regions define what belongs to the component, what remains optional, and where semantic responsibility lives.

1

Tablist

Required

Named container coordinating arrow-key navigation.

[role=tablist]
2

Tab

Required

Roving-focus button with label and optional icon.

button[role=tab]
3

Active indicator

Required

2px accent line along the active tab.

4

Panel

Required

Consumer-rendered view associated through useTabPanelProps.

[role=tabpanel]

Construction and authoring

The Figma-equivalent asset model, auto-layout, resizing, properties, slots, content bounds, localization, and governance contract.

Asset kind

component

Design library name

Components/Navigation/Tabs

Maturity

stable

Last reviewed

2026-08-29

Canvas applicability

Publish a component set with active-tab variants and nested tab instances.

Auto layout

Direction
horizontal
Gap
2.5px
Padding
0px
Alignment
End aligned on the active indicator
Wrap
No wrap
  • Measurements use the 20px playground and Figma reference root. The package does not set html font-size. Rem-based dimensions scale with the consumer root; literal px dimensions remain fixed.

Resizing

Width
hug
Height
hug
Minimum width
Content width
Maximum width
Parent or viewport width
Minimum height
Content-derived: 45px for one line
Maximum height
Content controlled
Overflow
visible

Exposed design properties

PropertyTypeDefaultCode mappingOptions or notes
Active previewRequiredvariantoverviewFinite starter keys; custom tabs edit each nested Selected stateoverview, activity, settings
State previewvariantdefaultKeyboard focus on the active starter tabdefault, focus-visible
TabsRequiredslotNonetabs; attached Tab instancesNo additional constraint
Label (nested Tab)textOverviewTab.labelNo additional constraint
Show icon (nested Tab)booleanfalseBoolean(Tab.icon)No additional constraint
Icon (nested Tab)instance-swapNoneTab.icon; source icon example is 24px, while consumer code owns dimensionsNo additional constraint

Nested assets and slots

Tab list

primitive / required

Keyboard navigation container.

<div role="tablist">

Tab

subcomponent / required

Repeatable label, optional icon, and indicator.

Tab data item

Tab panel

helper / required

Consumer-owned related content panel.

useTabPanelProps

Content limits

Tabs

Recommended two to five peer views

Overflow: Use page navigation or another information architecture for larger sets.

All labels should remain visible without horizontal ambiguity.

Tab label

One or two words, maximum 20 characters

Overflow: Do not truncate.

Short labels improve comparison and keyboard predictability.

Localization and RTL

Translatable: Tab list label, Tab labels

  • Visual order follows document direction.
  • Left and right arrow expectations must be tested for the supported browser behavior.
  • Test all labels at twice English length.
  • Test panel relationships after translation.

Responsive behavior

Intrinsic single row owned by its container.

Parent-selected narrow breakpoint

  • Do not wrap tab rows.
  • Use horizontal scrolling only with an explicit overflow affordance, otherwise choose a different navigation pattern.

Authoring limits

  • Prototype active variants do not validate roving focus or panel relationships.
  • The required label is an accessibility-only tablist name; it has no visible text property in the canvas asset.
  • Consumers must pass the same stable id to Tabs and useTabPanelProps.
  • Generic tab keys and the tablist accessible label remain code-owned.

Accountable owner

Design systems navigation primitive owner

Canonical source: src/components/Tabs.tsx

  • Changes to tab order or activation require keyboard and information-architecture review.
  • A breaking property, token, or behavior change requires design and engineering approval, a migration note, and a major release.
  • The design asset, implementation, documentation, accessibility contract, and regression coverage must ship in the same change.
Read the system construction standard

Visual specification

These measurements and semantic tokens define the supported visual contract. Local overrides should preserve the same hierarchy and interaction cues.

Tab padding

20px horizontal / 10px vertical

Tab gap

2.5px

Icon/label gap

10px

Active indicator

2px high

Top radius

6px

Rules

  • Use one concise row when possible.
  • The active state combines background, text, and indicator, not color alone.
  • Render only peer views that share the same page context.
  • Measurements use the 20px playground and Figma reference root. The package does not set html font-size. Rem-based dimensions scale with the consumer root; literal px dimensions remain fixed.

Responsive behavior

  • The consumer should provide horizontal scrolling or an alternate pattern if labels overflow.
  • Do not wrap one tablist over multiple lines.

Token dependencies

--color-highlight

Active tab background.

--color-accent

Active indicator.

--color-text / --color-text2 / --color-text3

Active, hover, and inactive hierarchy.

--motion-fast

Color transition.

States and behavior

A component is not complete until its passive, interactive, disabled, and exceptional states remain understandable in both themes.

active

Trigger
Tab key equals active.
Visual response
Highlight background, primary text, and accent indicator.
Behavior
tabIndex is 0; associated panel is visible.
Accessibility
aria-selected true.

inactive

Trigger
Tab key differs from active.
Visual response
Tertiary text that strengthens on hover.
Behavior
tabIndex is -1; activation selects it.
Accessibility
aria-selected false.

focus-visible

Trigger
Roving focus reaches a tab.
Visual response
Global button focus outline.
Behavior
Arrow, Home, and End select and focus another tab.

Accessibility contract

Semantics, accessible naming, keyboard behavior, focus and announcements are implementation requirements, not optional documentation.

Semantics
Explicit tablist, tab, and tabpanel roles with aria-selected, aria-controls, and aria-labelledby.
Accessible name
Required label names the tablist; each tab label names its tab.
  • Pass the same stable id to Tabs and useTabPanelProps so relationships are emitted.
  • Render one panel for every tab key and hide inactive panels.
  • Keep tab keys DOM-id safe and unique.
  • Icons are decorative.

Keyboard behavior

Arrow Right / Arrow Left
Selects and focuses the next / previous tab with wraparound.
Home / End
Selects and focuses the first / last tab.
Enter / Space
Native button activation selects a focused tab.
Tab
Moves from the active tab into the active panel or next focus target.

Implementation

Use the public package API and preserve the controlled-state, native-attribute, and ref contracts described below.

tsx
import { Tabs, useTabPanelProps, type Tab } from '@ai-created/ui';

Client Component required

  • Tabs is controlled and uses automatic activation during arrow navigation.
  • Without a shared provided id, DOM ids are generated but cross-component aria relationships are intentionally omitted.
  • useTabPanelProps returns role, ids, tabIndex, and hidden.
tsx
const panel = useTabPanelProps("overview", active, tabsId);
<Tabs id={tabsId} tabs={tabs} active={active} onChange={setActive} label="Project views" />
<div {...panel}>Overview content</div>

Public API

These props and helpers are compatibility contracts. Changes require migration guidance and release notes.

PropTypeDefaultContract
tabsTab<T>[]requiredKeys, labels, and optional icons.
activeTrequiredActive tab key.
onChange(key: T) => voidrequiredCalled when tab changes.
labelstringrequiredTablist accessible label.
idstringgenerated idStable group id for panels.

Usage guidance

These rules keep the component recognizable across products without preventing deliberate composition.

Do

  • Use for two to five related peer views.
  • Keep labels short and use a stable default tab.

Do not

  • Do not use tabs for primary site navigation.
  • Do not place unrelated tasks in the same tablist.

Testing contract

The component should be verified as rendered UI, an interaction model, an accessibility surface, and a theme-aware visual artifact.

Unit

  • Emits ids and panel relationships only when the stable id is shared.
  • Handles empty tabs without errors.

Interaction

  • Click, arrow wraparound, Home, End, focus movement, and panel visibility work.

Accessibility

  • Roving tabIndex, selected state, tablist name, and panel relationships are valid.

Visual

  • Capture each active tab, focus, optional icons, overflow pressure, and themes.

Related specifications