Toggle Group
Toggle buttons that share one value. Use it to pick a layout, a time range, or a theme, or to turn several text styles on at once.
Variants and sizes
default is borderless, outline draws a control border on each item. Items sit 8px apart by default.
Small
28px · split byDefault
32px · icon only, one disabledLarge
36px · icon and labelSegmented controls
spacing={0} joins outline items into one control. Value is controlled and always keeps one choice: pressing the active item again changes nothing.
Usage
Credits in the last 30 days · UTC
| Model | Credits |
|---|---|
| claude-sonnet-4 | 182.4 |
| gpt-4.1-mini | 64.15 |
| text-embedding-3-large | 9.8 |
Table toolbar
Icon and label items pick the layout. The whole group is disabled while rows load, and the toolbar stacks on narrow widths.
Settings row
A small segmented control as the value of a settings row. This sample keeps the choice in local state.
Preferences
Theme
Sample theme: System
Vertical and multiple
multiple lets several items stay pressed. orientation='vertical' stacks items; Up and Down arrows move focus.
Applied: bold, italic
Usage
import { ToggleGroup, ToggleGroupItem } from "@tulipfarm/sprout/toggle-group";
const [range, setRange] = useState(30);
<ToggleGroup
aria-label="Time range"
variant="outline"
size="sm"
spacing={0}
value={[String(range)]}
onValueChange={(value) => {
// Keep one choice: ignore a press that would clear it.
if (value[0]) setRange(Number(value[0]));
}}
>
<ToggleGroupItem value="7">7d</ToggleGroupItem>
<ToggleGroupItem value="30">30d</ToggleGroupItem>
</ToggleGroup>
<ToggleGroup aria-label="Text style" multiple defaultValue={["bold"]}>
<ToggleGroupItem value="bold" aria-label="Bold"><Bold /></ToggleGroupItem>
<ToggleGroupItem value="italic" aria-label="Italic"><Italic /></ToggleGroupItem>
</ToggleGroup>The value is always an array of item values. Pass value andonValueChange to control it, or defaultValue. Without multiple, pressing an item releases the others, and pressing the active item again sends an empty array. Ignore an empty array, as above, when one choice must stay selected. GiveToggleGroup a type, as in <ToggleGroup<Layout>>, to type the values.
Props
variant is "default" (no border) or "outline" (a control border on each item). size is "sm"(28px, 12px text), "default" (32px), or "lg" (36px). Items inherit both from the group.
spacing is the gap between items in 4px steps and defaults to 2 (8px). spacing={0} joins the items into one segmented control: inner corners are square and outline items share one border. orientation is "horizontal" (default) or "vertical".
disabled on the group disables every item; on an item it disables only that item. Icons are 16px (14px in sm) unless they set their own size. Mark a leading or trailing icon with data-icon="inline-start" or "inline-end" to tighten padding. Both parts take Base UI props such as render, loopFocus, and state functions for className.
Accessibility
The group renders role="group"; name it with aria-label. Each item is a button with aria-pressed. Tab moves into the group once. Left and Right arrows (Up and Down when vertical) move between items and loop at the ends; Home and End jump to the first and last. Space or Enter presses the focused item. Disabled items are skipped. An icon-only item needs its own aria-label.
Color changes take 120ms and stop when reduced motion is requested.
Theme tokens
Pressed items use --sprout-primary-subtle and --sprout-primary, so the TulipFarm theme tints them green. Idle items use --sprout-muted, hover uses --sprout-hover, outline borders use --sprout-input, and the focus ring uses --sprout-focus.