Tabs
Tabs switch between related views in the same place.
import { Tabs } from '@aksornproject/aksara-ui'Basic tabs
Tabs.Root holds the selection. Tabs.List is the tab row and needs an aria-label or aria-labelledby. Each Tabs.Tab and Tabs.Panel pair shares a value, a string or a number. defaultValue picks the first selected tab.
<Tabs.Root defaultValue="overview" className="w-full">
<Tabs.List aria-label="Course views">
<Tabs.Tab value="overview">Overview</Tabs.Tab>
<Tabs.Tab value="lessons">Lessons</Tabs.Tab>
<Tabs.Tab value="grades">Grades</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="overview">
Algebra for upper secondary students, taught over 12 weeks.
</Tabs.Panel>
<Tabs.Panel value="lessons">
24 lessons, from linear equations to quadratic functions.
</Tabs.Panel>
<Tabs.Panel value="grades">
Grades appear here after the first assignment.
</Tabs.Panel>
</Tabs.Root>Sizes
size on the Root sets the tab height for every tab. small is 40px and the default, medium is 44px and large is 48px.
<div className="flex w-full flex-col gap-spacing-16">
{sizes.map((size) => (
<Tabs.Root key={size} size={size} defaultValue="overview">
<Tabs.List aria-label={`Course views, ${size}`}>
<Tabs.Tab value="overview">Overview</Tabs.Tab>
<Tabs.Tab value="lessons">Lessons</Tabs.Tab>
<Tabs.Tab value="grades">Grades</Tabs.Tab>
</Tabs.List>
</Tabs.Root>
))}
</div>Slots and disabled tabs
leading sits before the label. selectedContent shows only while the tab is selected and always reserves its box, so selection never moves the row. Both are decorative. endContent holds compact noninteractive content, such as a count, and its text is part of the tab name.
disabled keeps a tab focusable but it never activates.
<Tabs.Root defaultValue="saved" className="w-full">
<Tabs.List aria-label="Library views">
<Tabs.Tab value="search" leading={<IconInterfaceEssentialSearch />}>
Search
</Tabs.Tab>
<Tabs.Tab
value="saved"
selectedContent={<IconInterfaceEssentialDoneCheck />}
>
Saved
</Tabs.Tab>
<Tabs.Tab value="assigned" endContent={<span>3</span>}>
Assigned
</Tabs.Tab>
<Tabs.Tab value="archived" disabled>
Archived
</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="search">
Search the library by title or topic.
</Tabs.Panel>
<Tabs.Panel value="saved">Worksheets you saved for later.</Tabs.Panel>
<Tabs.Panel value="assigned">
Three worksheets are due this week.
</Tabs.Panel>
</Tabs.Root>Menu tabs
Tabs.Menu is a tab that opens a menu of options. Pass Menu content to menu. It has its own value and panel like a regular tab. Click, Enter and Space select it and open the popup. Arrow keys open the popup without selecting.
Selection and the open state stay independent. open, defaultOpen and onOpenChange control the popup like Menu.Root.
<Tabs.Root defaultValue="details" className="w-full">
<Tabs.List aria-label="Course views">
<Tabs.Tab value="details">Details</Tabs.Tab>
<Tabs.Tab value="units">Units</Tabs.Tab>
<Tabs.Menu
value="versions"
menu={
<>
<Menu.Item>Published</Menu.Item>
<Menu.Item>Drafts</Menu.Item>
</>
}
>
Versions
</Tabs.Menu>
</Tabs.List>
<Tabs.Panel value="details">
Course title, subject and grade level.
</Tabs.Panel>
<Tabs.Panel value="units">Five units, in teaching order.</Tabs.Panel>
<Tabs.Panel value="versions" keepMounted>
Pick a version from the menu.
</Tabs.Panel>
</Tabs.Root>Fill layout
layout="fill" on the List shares the row equally, with a 96px minimum per tab. Long labels truncate, and the list scrolls when the tabs do not fit. The default hug layout sizes each tab to its label.
<Tabs.Root defaultValue="students" className="w-full max-w-[480px]">
<Tabs.List aria-label="Class views" layout="fill">
<Tabs.Tab value="students">Students</Tabs.Tab>
<Tabs.Tab value="assignments">Assignments</Tabs.Tab>
<Tabs.Tab value="attendance">Attendance</Tabs.Tab>
</Tabs.List>
</Tabs.Root>Actions and overflow
actions holds your buttons after a vertical separator. overflow holds a button or menu trigger at the end of the row. Both sit outside the tablist, so they are not tabs. divider={false} removes the rule under the row.
<Tabs.Root defaultValue="students" className="w-full">
<Tabs.List
aria-label="Class views"
actions={
<Button size="xs" variant="tertiary-accent">
Export
</Button>
}
overflow={
<Menu.Root>
<Menu.Trigger
aria-label="More actions"
render={<button type="button" />}
>
<IconInterfaceEssentialDots />
</Menu.Trigger>
<Menu.Portal>
<Menu.Positioner align="end">
<Menu.Popup>
<Menu.Item>Print</Menu.Item>
<Menu.Item>Archive class</Menu.Item>
</Menu.Popup>
</Menu.Positioner>
</Menu.Portal>
</Menu.Root>
}
>
<Tabs.Tab value="students">Students</Tabs.Tab>
<Tabs.Tab value="assignments">Assignments</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="students">28 students enrolled.</Tabs.Panel>
<Tabs.Panel value="assignments">4 assignments this term.</Tabs.Panel>
</Tabs.Root>Controlled tabs
Pass value and onValueChange to control the selection. onValueChange reports the next value as string | number | null with the Base UI event details. value and defaultValue cannot be combined, and null selects nothing.
Showing the week view.
<div className="flex w-full flex-col gap-spacing-8">
<Tabs.Root value={value} onValueChange={setValue}>
<Tabs.List aria-label="Schedule range">
<Tabs.Tab value="day">Day</Tabs.Tab>
<Tabs.Tab value="week">Week</Tabs.Tab>
<Tabs.Tab value="month">Month</Tabs.Tab>
</Tabs.List>
</Tabs.Root>
<p>Showing the {value} view.</p>
</div>Accessibility
- Arrow keys move focus without selecting. Enter and Space select. Home and End jump to the ends, and focus loops by default.
activateOnFocusandloopFocuson the List change this. - Base UI supplies the roving tabindex and links each tab to its panel.
- The List requires an accessible name. TypeScript rejects a List without
aria-labeloraria-labelledby. - Menu tabs expose
aria-haspopup="menu"andaria-expanded. Escape closes the popup and returns focus to the tab. leading,selectedContent, the chevron, the indicator and the divider arearia-hidden.endContentstays in the accessible name.- Only horizontal tabs exist.
orientationacceptshorizontalalone.
API
Tabs.Root
Prop
Type
Tabs.List
Prop
Type
Tabs.Tab
Prop
Type
Tabs.Menu
Prop
Type
Tabs.Panel
Prop
Type