Skip to Content
⭐️ Leave a star →
ComponentsTabs

Tabs

Accessible tabs with horizontal/vertical orientation, automatic or manual activation, and full keyboard navigation. Currently only available in React.

Features

Horizontal or vertical orientation — controls arrow-key navigation direction.
Automatic activation (focus selects) or manual (Enter/Space to activate).
Full keyboard navigation: arrows, Home, End.
Skips disabled triggers during arrow-key navigation.
Optional forceMount on Content to keep panels mounted (preserves state).
Controlled or uncontrolled value.

Example

A high-level summary of the product features and what makes it special.
import { Tabs } from '@wire-ui/react' <Tabs.Root defaultValue="overview"> <Tabs.List> <Tabs.Trigger value="overview">Overview</Tabs.Trigger> <Tabs.Trigger value="details">Details</Tabs.Trigger> <Tabs.Trigger value="reviews">Reviews</Tabs.Trigger> </Tabs.List> <Tabs.Content value="overview">Overview content.</Tabs.Content> <Tabs.Content value="details">Details content.</Tabs.Content> <Tabs.Content value="reviews">Reviews content.</Tabs.Content> </Tabs.Root>

Styling

Trigger and Content expose data-state ("active" / "inactive") and data-orientation. Trigger also exposes the full interactive state set plus data-disabled.

<Tabs.Trigger className=" border-b-2 border-transparent data-[state=active]:border-black data-[state=active]:font-semibold data-[disabled]:opacity-40 data-[focus-visible]:ring-2 "> Tab </Tabs.Trigger>

For vertical tabs, switch the indicator to the side:

<Tabs.Root orientation="vertical"> <Tabs.List className="flex flex-col border-r border-black"> <Tabs.Trigger value="x" className="border-r-2 border-transparent data-[state=active]:border-black" /> </Tabs.List> </Tabs.Root>

Using data attributes

[data-state="active"] { border-color: #000; font-weight: 600; } [data-state="inactive"] { /* default */ } [data-orientation="vertical"] { flex-direction: column; } [data-disabled] { opacity: 0.4; cursor: not-allowed; }

Root props

PropTypeDefaultDescription
valuestringControlled active tab value
defaultValuestringInitial active tab (uncontrolled)
onChange(value: string) => voidCalled when the active tab changes
orientation'horizontal' | 'vertical''horizontal'Layout direction; controls arrow-key axis
activationMode'automatic' | 'manual''automatic'automatic: focus activates; manual: Enter/Space activates

Trigger props

PropTypeDefaultDescription
valuestringrequiredUnique value identifying this tab
disabledbooleanfalseDisable this tab

Content props

PropTypeDefaultDescription
valuestringrequiredThe tab value this panel is associated with
forceMountbooleanfalseKeep mounted in the DOM and toggle visibility via hidden + data-state

Data attributes

AttributeElementValues
data-stateTrigger, Content"active" / "inactive"
data-orientationRoot, List, Trigger, Content"horizontal" / "vertical"
data-disabledTriggerPresent when disabled
data-hover / data-active / data-focus-visibleTriggerStandard interactive states

Trigger sets role="tab", aria-selected, aria-controls, and tabIndex={0} only for the active tab (roving tabindex). Content sets role="tabpanel", aria-labelledby, and tabIndex={0}. List sets role="tablist" and aria-orientation.

Accessibility

  • Implements the WAI-ARIA tabs pattern with roving tabindex.
  • Arrow keys navigate; disabled triggers are skipped automatically.
  • automatic activation moves selection along with focus (most common). Use manual for tabs whose content is expensive to mount.

Keyboard Interactions

KeyDescription
ArrowRight / ArrowDownFocus next trigger (axis depends on orientation).
ArrowLeft / ArrowUpFocus previous trigger.
HomeFocus the first trigger.
EndFocus the last trigger.
Enter / SpaceActivates the focused tab (manual mode only).
TabMoves focus into the active panel.
Last updated on

MIT License © 2026 wire-ui

Tabs – Wire UI