Set
Default
Choose the alignment for the heading.
Subtle
The caption uses a quieter control with the same selection behavior.
Selects one visible option. Default joins toggles with an ink active state; subtle uses a gray rail, 3px gaps, and a soft active fill.
Default
Choose the alignment for the heading.
Subtle
The caption uses a quieter control with the same selection behavior.
Three ways in. They share one source, so the pixels match whichever you pick.
npm install @noorddev/vlak-react
// once, next to your app's root
import "@noorddev/vlak-react/css";
import { ToggleGroup } from "@noorddev/vlak-react";Precompiled React and one stylesheet. No compiler to configure. Per-component imports work too: @noorddev/vlak-react/components/toggle-group.
npx @noorddev/vlak-cli add toggle-group
The StyleX leaf lands in components/vlak/ with its dependencies, for your own compiler to own. See StyleX.
npx shadcn add https://vlak.dev/r/toggle-group.json
The same registry item, installed by shadcn's CLI.
<link rel="stylesheet" href="node_modules/@noorddev/vlak/css/vlak.css" />
No React. Link vlak.css and use the markup and classes below.
import { useState } from "react";
import { ToggleGroup } from "@noorddev/vlak-react";
const [align, setAlign] = useState("left");
<ToggleGroup
variant="subtle"
aria-label="Alignment"
options={[
{ value: "left", label: "Left" },
{ value: "center", label: "Center" },
{ value: "right", label: "Right" },
]}
value={align}
onValueChange={setAlign}
/>One pressed at a time.
| Prop | Type | Default | Description |
|---|---|---|---|
optionsrequired | { value: string; label: ReactNode; }[] | ||
value | string | ||
defaultValue | string | ||
onValueChange | (value: string) => void | ||
variant | "subtle" | "default" | "default" | Subtle groups use a soft rail and individually rounded selected items. |
Also accepts Omit<HTMLAttributes<HTMLDivElement>, "onChange">.
| Keys | Does |
|---|---|
| Tab | Moves between the options |
| Enter, Space | Selects the focused option |
<div class="rs-toggle-group" role="group" aria-label="Default alignment"><button class="rs-toggle rs-toggle-grouped rs-toggle-pressed rs-toggle-grouped-on" aria-pressed="true">Left</button><button class="rs-toggle rs-toggle-grouped" aria-pressed="false">Center</button><button class="rs-toggle rs-toggle-grouped" aria-pressed="false">Right</button></div> <div class="rs-toggle-group rs-toggle-group-subtle" role="group" aria-label="Subtle alignment"><button class="rs-toggle rs-toggle-grouped rs-toggle-pressed rs-toggle-grouped-on rs-toggle-subtle rs-toggle-subtle-pressed rs-toggle-grouped-subtle" aria-pressed="true">Left</button><button class="rs-toggle rs-toggle-grouped rs-toggle-subtle rs-toggle-grouped-subtle" aria-pressed="false">Center</button><button class="rs-toggle rs-toggle-grouped rs-toggle-subtle rs-toggle-grouped-subtle" aria-pressed="false">Right</button></div>