Toggle

Turns one persistent option on or off with aria-pressed. Default uses an ink fill when pressed; subtle uses a soft fill and stronger text.

Grid

Keep the grid visible and choose the helpers used while arranging the sheet.

Use it for

  • A formatting or filter option that is on or off and stays in view.
  • Default for a bordered toggle with an ink pressed state. Subtle stays transparent on hover while muted text turns to ink; pressing adds a soft fill and stronger text.
  • Several independent toggles in a row.

Not for

  • A setting that applies immediately to the app; use Switch.
  • One of several; use ToggleGroup.

Three ways in. They share one source, so the pixels match whichever you pick.

1. Import the package

npm install @noorddev/vlak-react

// once, next to your app's root
import "@noorddev/vlak-react/css";

import { Toggle } from "@noorddev/vlak-react";

Precompiled React and one stylesheet. No compiler to configure. Per-component imports work too: @noorddev/vlak-react/components/toggle.

2. Vendor the source

npx @noorddev/vlak-cli add toggle

The StyleX leaf lands in components/vlak/, for your own compiler to own. See StyleX.

3. Through shadcn

npx shadcn add https://vlak.dev/r/toggle.json

The same registry item, installed by shadcn's CLI.

CSS only

<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 { Toggle } from "@noorddev/vlak-react";

const [bold, setBold] = useState(false);
const [italic, setItalic] = useState(false);

<Toggle pressed={bold} onPressedChange={setBold}>Bold</Toggle>
<Toggle variant="subtle" pressed={italic} onPressedChange={setItalic}>Italic</Toggle>
<Toggle variant="subtle" defaultPressed>Underline</Toggle>
<Toggle variant="subtle" disabled>Strikethrough</Toggle>

Toggle

Press switch; state lives in aria-pressed.

PropTypeDefaultDescription
pressedboolean
defaultPressedboolean
onPressedChange(pressed: boolean) => void
variant"subtle" | "default""default"Subtle uses a quiet hover and a soft selected fill.

Also accepts Omit<ButtonHTMLAttributes<HTMLButtonElement>, "onChange">.

ToggleGroup

One pressed at a time.

PropTypeDefaultDescription
optionsrequired{ value: string; label: ReactNode; }[]
valuestring
defaultValuestring
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">.

KeysDoes
TabMoves focus to the toggle
Enter, SpacePresses or releases it
<button class="rs-toggle rs-toggle-pressed" aria-pressed="true">Bold</button>
<button class="rs-toggle rs-toggle-subtle" aria-pressed="false">Italic</button>
<button class="rs-toggle rs-toggle-pressed rs-toggle-subtle rs-toggle-subtle-pressed" aria-pressed="true">Underline</button>
<button class="rs-toggle rs-toggle-subtle" aria-pressed="false" disabled>Strikethrough</button>
.rs-toggle.rs-toggle-group.rs-toggle-grouped.rs-toggle-grouped-on.rs-toggle-pressed.rs-toggle-subtle.rs-toggle-subtle-pressed.rs-toggle-group-subtle.rs-toggle-grouped-subtle