@biem/ui

Tabs

A set of panels that lets users switch between related content.

Tabs divide related content into panels and show one panel at a time. Each trigger names its panel, so users can scan the list and open only the content they need.

The store receives 12 cases from the warehouse on Tuesday.

Usage

tabs-default.tsx
import {
	Tabs,
	TabsContent,
	TabsList,
	TabsTrigger,
} from "@biem/ui/components/ui/tabs";

export function TabsDefault() {
	return (
		<div className="w-full max-w-sm">
			<Tabs defaultValue="incoming">
				<TabsList>
					<TabsTrigger value="incoming">Incoming</TabsTrigger>
					<TabsTrigger value="outgoing">Outgoing</TabsTrigger>
					<TabsTrigger value="completed">Completed</TabsTrigger>
				</TabsList>
				<TabsContent value="incoming">
					The store receives 12 cases from the warehouse on Tuesday.
				</TabsContent>
				<TabsContent value="outgoing">
					The store returns 4 cases to the warehouse on Thursday.
				</TabsContent>
				<TabsContent value="completed">
					The store checked in 36 cases from 3 transfers this week.
				</TabsContent>
			</Tabs>
		</div>
	);
}

Examples

Line

A page divided into sections, such as the stock, staff and revenue of one store, needs navigation that does not compete with its content. With variant set to "line", the list recedes behind those sections and only the active trigger keeps its emphasis, so users still see where they are.

The store receives 12 cases from the warehouse on Tuesday.

Muted

Inside a card, tabs often switch between views of the same figures, such as a week and a month. Here, variant set to "muted" lets the list blend into the card, while the active trigger stays marked and tells users which view they are reading.

The store receives 12 cases from the warehouse on Tuesday.

Vertical

Longer sets of panels, such as the settings of a store, need more triggers than one row holds comfortably. Set to "vertical", orientation places the list beside the content and stacks its triggers, so the list grows with every new panel and users scan it from top to bottom.

The store receives 12 cases from the warehouse on Tuesday.

With Icon

Users who return to the same panels throughout the day learn to find a trigger by its icon before they read its name. The name still carries the meaning, so each trigger remains clear for those who meet the tabs for the first time.

The store receives 12 cases from the warehouse on Tuesday.

Controlled

Other parts of an interface sometimes need to open a specific panel, for example a notification that leads users straight to the deliveries of the day. Through value and onValueChange, the application holds the active trigger, so it can switch panels on its own and restore the panel users chose last.

The store receives 12 cases from the warehouse on Tuesday.

Disabled Trigger

Some panels have nothing to show yet, such as a daily report that exists only once the store has closed. A trigger that carries disabled stays within reach of the arrow keys and exposes its state to assistive technology, yet users cannot activate it, so they know the panel exists without opening it by mistake.

The store receives 12 cases from the warehouse on Tuesday.

API Reference

Tabs

Propvalue
Typeany
Default–
DescriptionSets the value of the active trigger and makes the tabs controlled. Update it in onValueChange. With null, no trigger is active.
PropdefaultValue
Typeany
Default0
DescriptionSets the value of the trigger that is active at first render. The tabs then track the active trigger themselves. If no trigger has this value, the tabs activate the first enabled trigger. With null, no trigger is active.
ProponValueChange
Type(value: any, eventDetails: TabsRootChangeEventDetails) => void
Default–
DescriptionRuns when users activate another trigger. It receives the value of that trigger. Uncontrolled tabs also run it when they choose the active trigger themselves: at first render without defaultValue, and whenever the active trigger is missing or disabled. The reason in eventDetails tells these cases apart.
Proporientation
Type"horizontal" | "vertical"
Default"horizontal"
DescriptionSets the direction of the layout. Horizontal places the list above the content, vertical places the list beside the content and stacks its triggers. The left and right arrow keys move through the triggers of a horizontal list, the up and down arrow keys those of a vertical list.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the tabs with another component.

TabsList

Propvariant
Type"default" | "line" | "muted"
Default"default"
DescriptionSets how the list shows the active trigger. "default" places the triggers on a muted bar and raises the active one above it. "line" removes the bar and draws a line under the active trigger, or beside it in vertical tabs. "muted" removes the bar and fills the active trigger with the muted color.
PropactivateOnFocus
Typeboolean
Defaultfalse
DescriptionActivates a trigger as soon as it receives focus, so the arrow keys change the content directly. Without it, users press Enter or Space to activate the focused trigger.
ProploopFocus
Typeboolean
Defaulttrue
DescriptionMoves focus from the last trigger to the first, and from the first to the last, when users keep pressing the arrow keys. With false, focus stops at both ends.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the list with another component.

TabsTrigger

Propvalue
Typeany
Default–
DescriptionIdentifies the trigger in value, defaultValue and onValueChange of the tabs, and connects it to the TabsContent with the same value. Every trigger needs one.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the trigger with another component.
PropnativeButton
Typeboolean
Defaulttrue
DescriptionDeclares whether the rendered element is a native button. Set it to false when render returns a different element.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents users from activating the trigger and exposes the disabled state to assistive technology. The arrow keys still move to it.

TabsContent

Propvalue
Typeany
Default–
DescriptionConnects the content to the TabsTrigger with the same value. The tabs show the content while that trigger is active. Every content needs one.
PropkeepMounted
Typeboolean
Defaultfalse
DescriptionKeeps the content in the DOM while another trigger is active, hidden from users. Without it, the tabs render only the active content.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the content with another component.