Tab
Pre-alphaThe registry and the CLI are not published yet.Roadmap

Tab

Presentational top tabs with controlled selection, badges, scrollable layouts and optional swipe between panels.

Activity
AllMentionsRequests

2

Maya mentioned youIn Launch checklist · 4m
Jon completed a taskHomepage review · 21m
Nora requested accessBrand assets · 1h

Installation

npx axiom add tab
pnpm dlx axiom add tab
yarn dlx axiom add tab
bun x axiom add tab

Also copies: icon, badge, text, tappable and useControllableState. Installs react-native-reanimated.

Colors come from tab.{underline,pill}.{default,selected,disabled} in the component tokens.

Usage

import { Tab } from "@/components/ui/tab";

<Tab value={section} onValueChange={setSection}>
	<Tab.List>
		<Tab.Item value="all">All</Tab.Item>
		<Tab.Item value="unread">Unread</Tab.Item>
		<Tab.Item value="archived">Archived</Tab.Item>
	</Tab.List>

	<Tab.Content>
		<Tab.Panel value="all">
			<Feed />
		</Tab.Panel>
		<Tab.Panel value="unread">
			<UnreadFeed />
		</Tab.Panel>
		<Tab.Panel value="archived">
			<Archive />
		</Tab.Panel>
	</Tab.Content>
</Tab>;

Props

Tab

PropTypeDefaultDescription
valuestringValue of the selected tab in controlled usage.
defaultValuestringInitial selection when the component owns its state.
onValueChange(value: string) => voidCalled after an enabled tab is pressed. Use it to swap nearby content, not to push a new screen.
childrenReactNodeA Tab.List and optional content.
View propsViewPropsPassed to the root View, including style, accessibility props and ref.

Tab.List

Tab.List renders a View by default. With scrollable, it renders a horizontal ScrollView and keeps each item at its natural width.

PropTypeDefaultDescription
variant'underline' | 'pill''underline'Uses an indicator below the label or a filled capsule behind it.
scrollablebooleanfalseChanges the list from View to ScrollView.
View or ScrollView propsViewProps | ScrollViewPropsPassed to the rendered native component. contentContainerStyle is available when scrollable is true.

Tab.Item

PropTypeDefaultDescription
valuestringStable identifier returned through onValueChange.
childrenReactNodeShort label. One or two words scan best.
iconIconName | ReactNodeOptional icon before the label. Avoid icons when every tab is already clear in text.
badgenumber | string | booleanCount, short status or dot next to the label.
disabledbooleanfalseBlocks selection and exposes the disabled accessibility state.
accessibilityLabelstringlabel textSpoken label when the visible text needs more context.
Tappable propsTappablePropsPassed to the press target. Internal press and layout handlers are composed with yours.

Tab.Content

Tab.Content is a View. It renders only the selected Tab.Panel.

PropTypeDefaultDescription
View propsViewPropsPassed to the content View.

Tab.Pager

Tab.Pager is a horizontal ScrollView with pagingEnabled. Use it instead of Tab.Content when users should be able to swipe between panels.

PropTypeDefaultDescription
ScrollView propsScrollViewPropsPassed to the pager. Internal layout and momentum handlers are composed with yours.

Tab.Panel

PropTypeDefaultDescription
valuestringValue of the Tab.Item this panel belongs to.
childrenReactNodeContent shown while that tab is selected.
View propsViewPropsPassed to the panel View. Its layout handler is composed with yours.

The indicator travels on a spring, and lands without animating the first time: it has nothing to travel from until the items have been measured. Reduced motion moves it without animation.

Tab sets the tab list, tab and selected accessibility roles. Panels are optional. Without Tab.Content or Tab.Pager, the screen can render its content elsewhere from the selected value.

Swipe to switch

Use Tab.Pager when the panels contain peer views such as feeds, inboxes or order lists. Use Tab.Content when a panel owns horizontal interaction, for example a carousel, a pannable chart or rows with swipe actions.

<Tab value={section} onValueChange={setSection} style={{ flex: 1 }}>
	<Tab.List>
		<Tab.Item value="all">All</Tab.Item>
		<Tab.Item value="mentions">Mentions</Tab.Item>
	</Tab.List>

	<Tab.Pager>
		<Tab.Panel value="all">
			<Feed />
		</Tab.Panel>
		<Tab.Panel value="mentions">
			<Mentions />
		</Tab.Panel>
	</Tab.Pager>
</Tab>

The pager needs a bounded width and height. It uses the native ScrollView paging behavior, measures each panel at runtime and updates the selected value when scrolling settles. Pressing a tab scrolls to the measured position of its panel. Off-screen panels stay hidden from the screen reader.

Tab.Pager passes its props to the underlying ScrollView, so scrollEnabled, decelerationRate, keyboard behavior and scroll callbacks remain configurable.

Use cases

Switching one data view

Tabs work when the content changes but the screen purpose stays the same. Keep the filter state local to the screen.

Orders
ActivePast
Order #1842

Shipped

Arrives Thursday · $88.90
Order #1831

Preparing

3 items · $126.00
<Tab value={status} onValueChange={setStatus}>
	<Tab.List>
		<Tab.Item value="active">Active</Tab.Item>
		<Tab.Item value="past">Past</Tab.Item>
	</Tab.List>
</Tab>

Categories that need horizontal scrolling

When labels cannot fit without shrinking, let the row scroll. The selected tab should be brought into view after selection.

Discover
For youTechnologyDesignScienceCulture
A smaller battery with a longer life8 min read
<Tab value={category} onValueChange={setCategory}>
	<Tab.List scrollable>
		{categories.map((item) => (
			<Tab.Item key={item.id} value={item.id}>
				{item.label}
			</Tab.Item>
		))}
	</Tab.List>
</Tab>

Compact mode switch with pills

The pill variant works for a short, local mode switch. For two or three equally sized options inside a form, prefer SegmentedControl.

Saved

Grid

Map

<Tab value={view} onValueChange={setView}>
	<Tab.List variant="pill">
		<Tab.Item value="grid" icon="grid">
			Grid
		</Tab.Item>
		<Tab.Item value="map" icon="map">
			Map
		</Tab.Item>
	</Tab.List>
</Tab>