Toggle Group
A set of two-state buttons that can be toggled on or off, with support for single or multiple selection.
Overview
The ToggleGroup component manages related toggle buttons. Use the default variant for lightweight ghost-button groups, the outline variant for bordered groups, and the segmented variant for single-selection controls with an animated thumb.
Usage
import {
ToggleGroup,
ToggleGroupItem,
} from "@tilt-legal/cubitt-components/toggle-group";<ToggleGroup defaultValue="center" groupVariant="segmented">
<ToggleGroupItem value="left">Left</ToggleGroupItem>
<ToggleGroupItem value="center">Center</ToggleGroupItem>
<ToggleGroupItem value="right">Right</ToggleGroupItem>
</ToggleGroup>Sync selection with the URL by providing a paramName. Single-select groups use a string value, while multi-select groups use a string array.
<ToggleGroup
defaultValue="week"
groupVariant="segmented"
paramClearOnDefault
paramName="view"
>
<ToggleGroupItem value="day">Day</ToggleGroupItem>
<ToggleGroupItem value="week">Week</ToggleGroupItem>
<ToggleGroupItem value="month">Month</ToggleGroupItem>
</ToggleGroup>ToggleGroupItem supports Base UI's render prop. Set nativeButton={false} when rendering a non-button element such as a link.
<ToggleGroup defaultValue="week" groupVariant="segmented">
<ToggleGroupItem value="day">Day</ToggleGroupItem>
<ToggleGroupItem
nativeButton={false}
render={<a href="#week" />}
value="week"
>
Week
</ToggleGroupItem>
</ToggleGroup>Examples
Segmented
Single-selection segmented groups use the same track, thumb, separator, and hover model as Tabs.
import {
ToggleGroup,
ToggleGroupItem,
} from "@tilt-legal/cubitt-components/toggle-group";
import {
TextAlignCenter,
TextAlignLeft,
TextAlignRight,
} from "@tilt-legal/cubitt-icons/ui/outline";
export default function Example() {
return (
<ToggleGroup defaultValue="center" groupVariant="segmented" size="lg">
<ToggleGroupItem aria-label="Align left" mode="icon" value="left">
<TextAlignLeft />
</ToggleGroupItem>
<ToggleGroupItem aria-label="Align center" mode="icon" value="center">
<TextAlignCenter />
</ToggleGroupItem>
<ToggleGroupItem aria-label="Align right" mode="icon" value="right">
<TextAlignRight />
</ToggleGroupItem>
</ToggleGroup>
);
}Default
Default groups behave like related ghost toggles and support multiple active items.
import {
ToggleGroup,
ToggleGroupItem,
} from "@tilt-legal/cubitt-components/toggle-group";
import {
TextBold,
TextItalic,
TextUnderline,
} from "@tilt-legal/cubitt-icons/ui/outline";
export default function Example() {
return (
<ToggleGroup defaultValue={["bold"]} size="lg">
<ToggleGroupItem aria-label="Toggle bold" value="bold">
<TextBold />
</ToggleGroupItem>
<ToggleGroupItem aria-label="Toggle italic" value="italic">
<TextItalic />
</ToggleGroupItem>
<ToggleGroupItem aria-label="Toggle underline" value="underline">
<TextUnderline />
</ToggleGroupItem>
</ToggleGroup>
);
}Outline
Outline groups add a contextual border around related toggle items.
import {
ToggleGroup,
ToggleGroupItem,
} from "@tilt-legal/cubitt-components/toggle-group";
import {
TextBold,
TextItalic,
TextUnderline,
} from "@tilt-legal/cubitt-icons/ui/outline";
export default function Example() {
return (
<ToggleGroup
defaultValue={["bold", "italic"]}
groupVariant="outline"
size="lg"
>
<ToggleGroupItem aria-label="Toggle bold" value="bold">
<TextBold />
</ToggleGroupItem>
<ToggleGroupItem aria-label="Toggle italic" value="italic">
<TextItalic />
</ToggleGroupItem>
<ToggleGroupItem aria-label="Toggle underline" value="underline">
<TextUnderline />
</ToggleGroupItem>
</ToggleGroup>
);
}Sizes
Segmented groups support text and icon-only layouts at each size.
<div className="flex flex-col items-start gap-10">
<ToggleGroup defaultValue="week" groupVariant="segmented" size="sm">
<ToggleGroupItem value="day">Day</ToggleGroupItem>
<ToggleGroupItem value="week">Week</ToggleGroupItem>
<ToggleGroupItem value="month">Month</ToggleGroupItem>
<ToggleGroupItem value="year">Year</ToggleGroupItem>
</ToggleGroup>
<ToggleGroup defaultValue="week" groupVariant="segmented" size="md">
<ToggleGroupItem value="day">Day</ToggleGroupItem>
<ToggleGroupItem value="week">Week</ToggleGroupItem>
<ToggleGroupItem value="month">Month</ToggleGroupItem>
<ToggleGroupItem value="year">Year</ToggleGroupItem>
</ToggleGroup>
<ToggleGroup defaultValue="week" groupVariant="segmented" size="lg">
<ToggleGroupItem value="day">Day</ToggleGroupItem>
<ToggleGroupItem value="week">Week</ToggleGroupItem>
<ToggleGroupItem value="month">Month</ToggleGroupItem>
<ToggleGroupItem value="year">Year</ToggleGroupItem>
</ToggleGroup>
</div>Separator
Use ToggleGroupSeparator inside segmented groups to split related options. Separators hide when the active thumb touches them.
import {
ToggleGroup,
ToggleGroupItem,
ToggleGroupSeparator,
} from "@tilt-legal/cubitt-components/toggle-group";
export default function Example() {
return (
<ToggleGroup defaultValue="day" groupVariant="segmented" size="lg">
<ToggleGroupItem value="day">Day</ToggleGroupItem>
<ToggleGroupItem value="week">Week</ToggleGroupItem>
<ToggleGroupSeparator />
<ToggleGroupItem value="month">Month</ToggleGroupItem>
<ToggleGroupItem value="year">Year</ToggleGroupItem>
</ToggleGroup>
);
}URL State
Sync toggle group selection with the URL.
<ToggleGroup defaultValue="week" groupVariant="segmented" paramName="view">
<ToggleGroupItem value="day">Day</ToggleGroupItem>
<ToggleGroupItem value="week">Week</ToggleGroupItem>
<ToggleGroupItem value="month">Month</ToggleGroupItem>
<ToggleGroupItem value="year">Year</ToggleGroupItem>
</ToggleGroup>Polymorphic
Render items through custom elements while preserving pressed state.
import {
ToggleGroup,
ToggleGroupItem,
} from "@tilt-legal/cubitt-components/toggle-group";
export default function Example() {
return (
<ToggleGroup defaultValue="week" groupVariant="segmented" size="lg">
<ToggleGroupItem value="day">Day</ToggleGroupItem>
<ToggleGroupItem
nativeButton={false}
render={<a href="#week" />}
value="week"
>
Week
</ToggleGroupItem>
<ToggleGroupItem
nativeButton={false}
render={<a href="#month" />}
value="month"
>
Month
</ToggleGroupItem>
<ToggleGroupItem value="year">Year</ToggleGroupItem>
</ToggleGroup>
);
}API Reference
ToggleGroup
The root container that manages toggle selection.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | string[] | - | Controlled selected value or values. |
defaultValue | string | string[] | - | Initial selected value or values for uncontrolled usage. |
onValueChange | (value: string | string[]) => void | - | Called when selection changes. |
multiple | boolean | auto | Enables multiple selection. Segmented groups always use single selection. |
groupVariant | "default" | "outline" | "segmented" | "default" | Visual group style. |
variant | "default" | "outline" | "default" | Toggle item variant for non-segmented groups. |
size | "sm" | "md" | "lg" | "md" | Toggle item size. |
disabled | boolean | false | Disables the whole group. |
loop | boolean | true | Whether keyboard focus loops. |
orientation | "horizontal" | "vertical" | "horizontal" | Group orientation. |
className | string | - | Additional classes for layout. |
URL State Props
| Prop | Type | Default | Description |
|---|---|---|---|
paramName | string | - | Search parameter name used for URL state. |
onUrlValueChange | (value: string | string[] | null) => void | - | Called when the URL-backed value changes. |
paramClearOnDefault | boolean | true | Removes the URL parameter when value matches the default. |
paramThrottle | number | - | Throttles URL updates in milliseconds. |
paramDebounce | number | - | Debounces URL updates in milliseconds. |
ToggleGroupItem
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | Required unique item value. |
mode | "icon" | - | Square icon-only sizing. Segmented icon items render circular. |
disabled | boolean | false | Disables one item. |
variant | "default" | "outline" | inherited | Overrides the item variant for non-segmented groups. |
size | "sm" | "md" | "lg" | inherited | Overrides the item size. |
render | ReactElement | function | - | Renders as a custom element or component. |
nativeButton | boolean | true | Set to false when render outputs a non-button element. |
className | string | - | Additional item classes. |
children | React.ReactNode | - | Item content. |
ToggleGroupSeparator
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional separator classes. |
Notes
- Use
multiplefor multi-select default or outline groups. - Segmented groups force single selection so the animated thumb always has one target.
- Use
aria-labelfor icon-only items. - The segmented variant respects
prefers-reduced-motion.