Tabs
Tabs that switch the panel under them, underlined, as pills or boxed on a track, with a sliding marker and the tabs that don't fit in a menu.
import { Tabs } from "@butteryui/react";Demo
Overview for Ines Vale.
When to use it
Use it for
- Sections of one record or page, such as a customer's overview, orders and notes
- A page header's views, under its title
- A quieter row, such as tabs inside a card, with variant="pills"; a few views of one thing, such as a chart, with variant="boxed"
Not for
- Tabs that go to other pages: use TabNav
- Two to five options that change one setting: use SegmentedControl
- Counts per view, such as orders by state: use StatTabs
Examples
Coffee views
A coffee's views in boxed tabs, its chosen tab raised on a track, and its brew guides in pills under them.
Peach, jasmine and bergamot, with a clean finish.
Customer page
A customer's page: the tabs sit in the page header, and each panel holds that part of the record.
Ines Vale
A customer since March, with 14 orders.
Customer sections
A customer's page split into sections, one panel at a time.
Ines has ordered 14 times since March.
Narrow tabs
More tabs than room: the last ones fold into "…" and stay one press away.
General settings
Read the note
The chosen tab kept in state, so a button outside the tabs can open one.
Ines left a note this morning.
Ines has ordered 14 times since March.
Variants and states
Underlined tabs
The underline slides to the chosen tab on spring.snappy; arrow keys move along the row.
Overview for Ines Vale.
Pills and boxed
pills slides a bg-control pill behind the chosen tab, with no line under the row; boxed raises the chosen tab on a bg-control track. Both slide on spring.snappy, as the underline does.
Orders for Ines Vale.
Orders for Ines Vale.
Not enough room
In a narrow column, the last tabs fold into the … menu, whichever the variant.
Overview
Overview
Props
Tabs
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | The chosen tab's value. Pair with onValueChange to control it. | |
defaultValue | string | The tab chosen at first when uncontrolled. | |
onValueChange | ((value: string) => void) | Called with the value of the tab chosen. | |
variant | "underline" | "pills" | "boxed" | "underline" | How the chosen tab is marked: "underline" (the default), a 2px underline on a line across the row, for a
page's sections; "pills", a bg-control pill behind it, for a quieter row; or "boxed", raised on a
bg-control track, for a few views of one thing. The marker slides on spring.snappy in each. |
It also takes Omit<ComponentPropsWithRef<typeof RadixTabs.Root>, "value" | "defaultValue" | "onValueChange" | "orientation" | "activationMode" | "asChild">.
Tabs.List
| Prop | Type | Default | Description |
|---|---|---|---|
labelrequired | string | Names the tabs for screen readers, such as "Order sections". | |
moreLabel | string | "More tabs" | Names the button that lists the tabs that don't fit. Defaults to "More tabs". |
It also takes Omit<ComponentPropsWithRef<typeof RadixTabs.List>, "asChild" | "aria-label">.
Tabs.Panel
| Prop | Type | Default | Description |
|---|---|---|---|
valuerequired | string | The value of the tab that shows this panel. |
It also takes Omit<ComponentPropsWithRef<typeof RadixTabs.Content>, "asChild">.
Tabs.Tab
| Prop | Type | Default | Description |
|---|---|---|---|
valuerequired | string | The value that names the tab and its panel. | |
childrenrequired | string | The tab's label. It's also its entry in the "…" menu once it doesn't fit. |
It also takes Omit<ComponentPropsWithRef<typeof RadixTabs.Trigger>, "asChild" | "children">.
Accessibility
A tablist named by its label; arrow keys move between tabs and choose them, Home and End jump to the ends, and Tab moves into the chosen panel, which is named by its tab. Tabs folded into the menu stay reachable from the More tabs button.
| Keys | What they do |
|---|---|
| Tab | Moves to the chosen tab, then to the More tabs button when some tabs have folded, then into the chosen panel |
| Arrow Right or Arrow Left | Moves to the next or previous tab in the row and shows its panel, wrapping at the ends |
| Home or End | Moves to the first or last tab in the row and shows its panel |
| Enter, Space or Arrow Down | Opens the More tabs menu from its button |
| Arrow Down or Arrow Up | Moves through the folded tabs in the menu |
| Enter or Space | Chooses the folded tab focused in the menu and shows its panel |
| Escape | Closes the menu and puts focus back on its button |
Motion
Its selection indicator slides to the chosen option on `spring.snappy`, inside one track.
With reduced motion: The underline, pill or raised tab appears on the chosen tab at once instead of sliding there.
Layout
It fills its container's width: a row of tabs, then the chosen panel 24px below. Underlined, the row sits over a 1px line and each tab is --bt-h-button (36px) tall, 16px from the next; as pills, the tabs are 36px pills 4px apart with no line; boxed, they sit 2px inside a 36px bg-control track (r-lg), each 32px tall (r-md). Each tab is as wide as its label and wholly its own hit area; labels never wrap or truncate: the tabs that don't fit fold into the More tabs menu at the row's end, last ones first, and the chosen tab stays in the row.
Related
See it in the Halfmoon shop demo.