Component
Toggle
A 38px key with a glyph or a medium label that holds the lilac (or turns white in outline) while pressed.
npx -y github:anwarlemu/inkbox-brand-cli#release add toggleUsage
Use for a two-state control that changes how something shows (bold, show archived, pin). Give an icon-only toggle an aria-label. For a group of exclusive choices use Toggle Group; for a setting use Switch.
Avoid
- A toggle that submits a form
- A purple filled toggle
- Icon motion when it turns on
Exports: Toggle, toggleVariants. This component is a client component.
Dependencies: radix-ui, class-variance-authority.
Example
"use client";import { ArchiveIcon, PushPinIcon, TextBIcon, TextItalicIcon } from "@phosphor-icons/react/ssr";import { Toggle } from "@/components/ui/toggle";export function Preview() { return ( <div className="flex flex-wrap items-center gap-2"> <Toggle aria-label="Pin the thread" defaultPressed> <PushPinIcon weight="fill" /> </Toggle> <Toggle> <ArchiveIcon weight="fill" /> Show archived </Toggle> </div> );}export function Variants() { return ( <div className="flex flex-wrap items-center gap-2"> <Toggle variant="outline" aria-label="Bold" defaultPressed> <TextBIcon weight="bold" /> </Toggle> <Toggle variant="outline" aria-label="Italic"> <TextItalicIcon weight="bold" /> </Toggle> <Toggle size="sm" aria-label="Pin, small"> <PushPinIcon weight="fill" /> </Toggle> <Toggle size="lg">Large</Toggle> <Toggle disabled>Disabled</Toggle> </div> );}Source
"use client";import * as React from "react";import { Toggle as TogglePrimitive } from "radix-ui";import { cva, type VariantProps } from "class-variance-authority";import { cn } from "@/lib/utils";// Extrapolated from the console's soft key (Tunnel quickstart) and its segmented choice (Where does this agent run?):// a 38px key with 8px corners, 8px of side padding and a 14px medium ink label beside a 20px glyph. Off it is bare and// washes lilac under the pointer; on it holds the lilac. `outline` adds the field edge and turns white with the Shadow/S// ring when on. In a ToggleGroup the default variant becomes the segmented track (see toggle-group). Pressing scales// it to 97 percent; the state change itself is a color change only.const toggleVariants = cva( "inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-control font-sans text-body leading-tight font-medium whitespace-nowrap text-fg outline-none select-none transition-[background-color,box-shadow,color,scale] duration-150 ease-out active:scale-97 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-focus-ring disabled:pointer-events-none disabled:opacity-50 aria-invalid:text-danger motion-reduce:transition-none motion-reduce:active:scale-100 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-5.5", { variants: { variant: { default: "bg-transparent hover:bg-subtle data-[state=on]:bg-subtle data-[state=on]:text-fg-brand", outline: "border border-line-field bg-surface hover:bg-subtle data-[state=on]:border-transparent data-[state=on]:bg-surface data-[state=on]:text-fg-brand data-[state=on]:shadow-s", }, size: { default: "h-9.5 min-w-9.5 px-2", sm: "h-8 min-w-8 px-1.5 text-body-sm [&_svg:not([class*='size-'])]:size-4", lg: "h-10.5 min-w-10.5 px-3", }, }, defaultVariants: { variant: "default", size: "default" }, },);function Toggle({ className, variant, size, ...props }: React.ComponentProps<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants>) { return <TogglePrimitive.Root data-slot="toggle" className={cn(toggleVariants({ variant, size, className }))} {...props} />;}export { Toggle, toggleVariants };Reference: Extrapolated from the Inkbox console (Figma 427:2715): the soft key (Tunnel quickstart) and the segmented choice.