Toggle

One control that stays pressed: bookmark, pin, mute, unread only. The single-item sibling of Toggle Group, sharing its paint and its heights, with a pressed glyph that fills in instead of blinking.

Installation#

# One-time setup (tokens + lib helpers)npx koalaui-cli@latest init# Add this component (its dependencies come along)npx koalaui-cli@latest add toggle

Usage#

usage.tsxTSX
import { Toggle } from "@/components/ui/toggle"export function Example() {  return <Toggle aria-label="Show grid">Show grid</Toggle>}

Anatomy#

import { Toggle, ToggleIcon } from "@/components/ui/toggle"<Toggle>  <ToggleIcon off={…} on={…} /></Toggle>

Variants#

outline (the default) is the Toggle Group pill: a framed control whose pressed state is an ink border and a soft halo, with no fill. ghost is bare at rest and takes the accent chip once pressed, the Toolbar's pressed look, for icon toggles in a row of other controls. Each is shown off, then on.

Sizes#

The Toggle Group scale: sm is 32px and md (the default) is 40px, so a lone toggle lines up with a group beside it. iconOnly squares the control around one glyph and steps the glyph up to 20px at md. The 32px control grows its target to 40px (44px on touch) without growing the visual.

Pressed glyph#

ToggleIcon holds two glyphs in one cell and cross-fades them on the toggle's state: the outgoing one shrinks to a quarter, fades and blurs as the incoming one resolves, on a CSS transition, so pressing twice quickly reverses mid-way instead of restarting. Pass the pressed glyph in its fill weight, which is how the system marks a selected state, or a different glyph when on means something else (a slashed microphone). Press them.

With a tooltip#

An icon-only toggle is named by its aria-label: the glyph is not a name. Show that name to sighted users with a Tooltip, and wrap the row in a TooltipGroup so the bubble glides from one toggle to the next.

Controlled#

Hold the state yourself with pressed and onPressedChange. Here it filters the list under it; the count is tabular-nums, so it never jitters as it changes.

Inbox 4
  • K
    Katie Park
    Launch checklist for Thursday
    Unread
  • D
    Diego Alvarez
    Re: pricing page copy
  • M
    Mia Chen
    Design review notes
    Unread
  • S
    Sam Okafor
    Quarterly numbers are in

Disabled#

disabled dims the control in either state and takes it out of the pointer's way, so a locked setting still shows which way it is set.

API reference#

Toggle

A <button> that stays pressed, with aria-pressed. Forwards all Radix Toggle Root props; every part accepts className, merged last.

PropTypeDefaultDescription
variant"outline" | "ghost""outline"outline is the Toggle Group pill (ink border and halo when pressed); ghost is bare and fills with the accent chip.
size"sm" | "md""md"32px or 40px tall; sm grows its hit target to 40px without growing the visual.
iconOnlybooleanfalseSquares the control around one glyph (20px at md). Name it with aria-label.
pressedboolean-The controlled pressed state.
defaultPressedbooleanfalseThe initial pressed state when uncontrolled.
onPressedChange(pressed: boolean) => void-Called when the pressed state changes.
disabledbooleanfalseDims the control in either state and blocks interaction.
asChildbooleanfalseRenders onto its child element instead of a <button>.
Data attributeDescription
data-state"on" while pressed, "off" otherwise.
data-disabledPresent when the toggle is disabled.

ToggleIcon

Two glyphs in one cell that cross-fade on the surrounding Toggle's state; decorative (aria-hidden), so it only works inside a Toggle. Forwards all native <span> props except children.

PropTypeDefaultDescription
off*React.ReactNode-The glyph at rest.
on*React.ReactNode-The glyph while pressed, usually the same icon in its fill weight.

FAQ#

A Switch is a setting that applies on its own (notifications on). A Toggle is a button that stays pressed, usually beside other controls (bookmark, mute, unread only). A Toggle Group is a set of them, holding one choice or several.