Skip to content
Drivn
5 min read

React Toggle Component Examples

Copy-paste React Toggle examples: a single pressed toggle, single and multiple groups, sizes, a disabled toggle, and a vertical group — all TypeScript.

A toggle is a two-state button that stays pressed — bold on or off, a view pinned or not — unlike a regular button that fires once and springs back. The Toggle component in Drivn is a plain React button with zero runtime UI dependencies: it tracks its pressed state with useState, reflects it through aria-pressed, and flips a data-[state=on] attribute that the Tailwind classes style. You install it with npx drivn add toggle, then use it standalone or grouped.

Every example below is TypeScript, because Drivn ships TypeScript-only .tsx source installed by the Drivn CLI under @/components/ui/toggle. The same file ships both forms via dot notation: a standalone Toggle and a Toggle.Group that coordinates several toggles through React context. The group takes type="single" for a one-active picker — like text alignment — or type="multiple" for an independent set like bold, italic, and underline, and it reads each child's pressed state from context instead of local state.

The examples cover a single pressed toggle, a single-selection group, a multiple-selection group, the three sizes, a disabled toggle, and a vertical group orientation.

A single pressed toggle

The simplest use is one standalone toggle that tracks its own on/off state. Drop in a Toggle with a label and an icon-as-component child, and it manages its pressed state internally with useState — no wiring required. Each click flips the state, sets aria-pressed for assistive tech, and toggles the data-[state=on] attribute that drives the active styling.

For controlled use, pass a pressed prop and an onChange callback to drive the state from your own store; for uncontrolled use, pass defaultPressed to set the starting value and let the component own it from there. This is the canonical pattern for a single boolean control that should read as a button rather than a checkbox — a "Bold" button in an editor toolbar, a "Pin" toggle on a card, a "Mute" control. The icon sits left of the label with the base style's gap-2.

1import { Toggle } from "@/components/ui/toggle"
2import { Bold } from "lucide-react"
3
4export default function Page() {
5 return (
6 <Toggle>
7 <Bold className="h-4 w-4" />
8 Bold
9 </Toggle>
10 )
11}

A single-selection group

To let exactly one toggle be active at a time — the text-alignment pattern — wrap several toggles in Toggle.Group with type="single". The group holds the selected value as a string and passes it down through React context; each child Toggle with a matching value reads its pressed state from that context instead of its own useState. Clicking an inactive toggle activates it and deactivates the previous one; clicking the active toggle clears the selection.

Use defaultValue for an uncontrolled group that manages itself, or pair value with onValueChange to control it from your own state. This is the right shape for any mutually exclusive choice rendered as buttons — alignment, a view mode switch, a single-pick filter. Because the same Toggle component detects the group context at render time, you reuse it unchanged inside or outside a group.

1<Toggle.Group type="single" defaultValue="center">
2 <Toggle value="left">
3 <AlignLeft className="h-4 w-4" />
4 </Toggle>
5 <Toggle value="center">
6 <AlignCenter className="h-4 w-4" />
7 </Toggle>
8 <Toggle value="right">
9 <AlignRight className="h-4 w-4" />
10 </Toggle>
11 <Toggle value="justify">
12 <AlignJustify className="h-4 w-4" />
13 </Toggle>
14</Toggle.Group>

A multiple-selection group

When several toggles should be independently on or off at once — the bold, italic, underline toolbar — use Toggle.Group with type="multiple". The group now holds its value as a string array, and each click adds or removes that toggle's value from the array. Every toggle reads whether its own value is in the array to decide its pressed state, so any combination can be active simultaneously.

This is the pattern for a rich-text formatting bar or any set of orthogonal options. Pass defaultValue={["bold", "italic"]} to start with several pressed, or control the array with value and onValueChange. The Toggle.Group accepts the same props in both modes — only type changes — so moving from single to multiple selection is a one-prop edit. Pair the result with a Button elsewhere in the toolbar for one-shot actions like "Clear formatting".

1<Toggle.Group type="multiple" defaultValue={["bold", "italic"]}>
2 <Toggle value="bold">
3 <Bold className="h-4 w-4" />
4 </Toggle>
5 <Toggle value="italic">
6 <Italic className="h-4 w-4" />
7 </Toggle>
8 <Toggle value="underline">
9 <Underline className="h-4 w-4" />
10 </Toggle>
11 <Toggle value="strikethrough">
12 <Strikethrough className="h-4 w-4" />
13 </Toggle>
14</Toggle.Group>

Sizes and the outline variant

The toggle ships three sizes — sm, md, and lg — set with the size prop, mapping to heights of h-8, h-9, and h-10 with matching horizontal padding in the styles.sizes object. The default is md. Alongside size, the variant prop switches between the default look — a transparent button that fills with bg-muted when pressed — and outline, which adds a border that adjusts on press, useful when toggles sit on a busy surface and need a visible resting edge.

Both props are typed against the styles object, so size and variant autocomplete to the exact allowed values with no magic strings. Mixing them is free: an outline toggle at size="lg" is just two props. Because the classes live in your installed Toggle file, you can retune any size or variant by editing the object directly rather than reaching for a config layer.

1<Toggle size="sm">
2 <Bold className="h-4 w-4" /> Sm
3</Toggle>
4<Toggle size="md">
5 <Bold className="h-4 w-4" /> Md
6</Toggle>
7<Toggle size="lg">
8 <Bold className="h-4 w-4" /> Lg
9</Toggle>

Disabled and vertical groups

Pass disabled to a single Toggle to drop it to 50% opacity and block clicks, or set disabled on a Toggle.Group to disable every toggle inside it — the group passes its disabled state down through context, and each child falls back to it when it has no disabled prop of its own. This is the clean way to grey out a whole formatting bar while a document is read-only.

For layout, Toggle.Group takes an orientation="vertical" prop that adds flex-col to stack the toggles in a column instead of a row — handy for a sidebar tool rail. Orientation is purely visual; selection behaviour is identical to a horizontal group. These two props compose with everything above, so a disabled, vertical, single-selection group is just three props on the group plus the toggles inside it.

1<Toggle disabled>
2 <Bold className="h-4 w-4" /> Bold
3</Toggle>
4
5<Toggle.Group type="single" defaultValue="left" orientation="vertical">
6 <Toggle value="left">
7 <AlignLeft className="h-4 w-4" />
8 </Toggle>
9 <Toggle value="center">
10 <AlignCenter className="h-4 w-4" />
11 </Toggle>
12 <Toggle value="right">
13 <AlignRight className="h-4 w-4" />
14 </Toggle>
15</Toggle.Group>
Get started

Install Drivn in one command

Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.

npx drivn@latest create

Requires Node 18+. Works with npm, pnpm, and yarn.

Enjoying Drivn?
Star the repo on GitHub to follow new component releases.
Star →

Frequently asked questions

A toggle is a two-state control that stays pressed until clicked again — like a bold button that holds its on state — and announces that state through aria-pressed. A regular button fires an action once and returns to rest. Use Toggle when the control represents an on/off state the user can see, and Button for one-shot actions.

Wrap them in Toggle.Group and choose a mode: type="single" holds one active value as a string, type="multiple" holds several as an array. Use defaultValue for an uncontrolled group, or pair value with onValueChange to control it from your own state. Each child Toggle reads its pressed state from the group context via its value prop.

No. The Toggle imports only React and a class-merge helper — it is a plain forwardRef button that tracks pressed state with useState and reflects it through aria-pressed and a data-state attribute. The grouped form uses a small React context rather than a second primitive, so npx drivn add toggle ships both the single and grouped toggle with zero runtime UI dependencies.

Yes. Set orientation="vertical" on the Toggle.Group and it adds flex-col to stack the toggles in a column instead of a row. Orientation only changes the layout — selection behaviour for single and multiple modes is identical to a horizontal group. This is useful for a sidebar tool rail or any vertical set of two-state controls.