Toggle
A button that stays on or off. Use it to turn on a text style, a filter, or a view option.
Variants and sizes
default has no border. outline draws a control border. Each size pairs a labeled toggle with an icon-only one.
Small
28px · filter chipDefault
32px · icon and labelLarge
36px · view optionStates
Off, on, disabled, and disabled while on. A disabled toggle keeps its pressed look so the saved value stays visible.
Formatting toolbar
Each toggle is controlled with pressed and onPressedChange. Tab moves between them; Space or Enter presses one.
Applied: Bold
Icon placement
Mark a leading or trailing icon with data-icon="inline-start" or "inline-end" to tighten that side by 2px.
Saving and errors
Disable the toggle and set aria-busy while a change saves. Set aria-invalid and describe the error when it fails.
Press Pin to sidebar to see the error.
toggleVariants
Give a Base UI Toggle the same look inside your own group. This is how Toggle Group items get their style.
Usage
import { Toggle } from "@tulipfarm/sprout/toggle";
<Toggle aria-label="Bold" defaultPressed>
<Bold />
</Toggle>
const [starred, setStarred] = useState(false);
<Toggle variant="outline" size="sm" pressed={starred} onPressedChange={setStarred}>
<Star data-icon="inline-start" />
Starred
</Toggle>Pass pressed and onPressedChange to control the toggle, or defaultPressed to let it keep its own state. While on, it hasaria-pressed="true" anddata-pressed.
Props
variant is "default" (no border) or "outline" (a control border). size is "sm" (28px, 12px text),"default" (32px), or "lg" (36px). Each size is at least as wide as it is tall, with 10px side padding.
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 on that side.
disabled blocks presses and dims the toggle. Setaria-invalid to draw a danger border, and aria-busy while a change saves. The toggle also takes Base UI props such asvalue, render, nativeButton, and state functions for className.
toggleVariants
import { Toggle } from "@base-ui/react/toggle";
import { ToggleGroup } from "@base-ui/react/toggle-group";
import { toggleVariants } from "@tulipfarm/sprout/toggle";
<ToggleGroup aria-label="Time range" defaultValue={["30d"]}>
<Toggle value="7d" className={toggleVariants({ variant: "outline", size: "sm" })}>
7d
</Toggle>
<Toggle value="30d" className={toggleVariants({ variant: "outline", size: "sm" })}>
30d
</Toggle>
</ToggleGroup>toggleVariants({ variant, size, className }) returns the class names of a toggle. Use it when you build your own group or render another element as a toggle. For a ready-made group, useToggle Group.
Accessibility
Toggle renders a button with aria-pressed. Tab moves focus to it, and Space or Enter presses it. A focused toggle shows a 2px focus ring. An icon-only toggle needs an aria-label. Keep the label the same when the state changes; screen readers already announce on or off.
Color changes take 120ms and stop when reduced motion is requested. In forced colors mode the toggle gets a border and the pressed toggle is highlighted.
Theme tokens
Off uses --sprout-muted, and hover uses --sprout-hover. On uses --sprout-primary on --sprout-primary-subtle, so the opt-in TulipFarm theme tints it green. Outline uses --sprout-input and --sprout-surface. Invalid uses --sprout-danger. Radius follows --sprout-radius-control.