Component
Toggle Group
The segmented choice: a lilac track of 38px choices where the chosen one is a white key with Shadow/S.
npx -y github:anwarlemu/inkbox-brand-cli#release add toggle-groupWhere does this agent run?
Usage
Use for a choice among a few options that changes what is shown next (Where does this agent run? Hermes, Openclaw, Codex, Claude Code). Use type single for one choice, multiple for several. Put a 24px logo tile or a 20px glyph before each label. Use variant outline for separate keys.
Avoid
- A purple chosen key
- A sliding indicator between choices
- More than seven choices in one track
Exports: ToggleGroup, ToggleGroupItem. This component is a client component.
Dependencies: toggle, radix-ui, class-variance-authority.
Example
"use client";import * as React from "react";import { CodeIcon, CodeBlockIcon, LightningIcon, RobotIcon, SparkleIcon, TerminalWindowIcon, TextAlignCenterIcon, TextAlignLeftIcon, TextAlignRightIcon } from "@phosphor-icons/react/ssr";import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";// The runners as 24px logo tiles; a real app puts each runner's own logo in the tile.const RUNNERS = [ { value: "hermes", label: "Hermes", icon: RobotIcon }, { value: "openclaw", label: "Openclaw", icon: LightningIcon }, { value: "codex", label: "Codex", icon: TerminalWindowIcon }, { value: "claude-code", label: "Claude Code", icon: SparkleIcon }, { value: "opencode", label: "OpenCode", icon: CodeBlockIcon },];export function Preview() { const [runner, setRunner] = React.useState("hermes"); return ( <div className="grid w-full gap-3"> <p id="runner" className="text-body leading-tight font-medium text-fg">Where does this agent run?</p> <ToggleGroup type="single" value={runner} onValueChange={(v) => v && setRunner(v)} aria-labelledby="runner" className="w-full"> {RUNNERS.map(({ value, label, icon: Icon }) => ( <ToggleGroupItem key={value} value={value}> <span className="flex size-6 items-center justify-center rounded-sm bg-surface text-fg-brand shadow-s"> <Icon weight="fill" className="size-4" /> </span> {label} </ToggleGroupItem> ))} <ToggleGroupItem value="other"> <CodeIcon weight="bold" /> Other </ToggleGroupItem> </ToggleGroup> </div> );}export function Outline() { return ( <ToggleGroup type="multiple" variant="outline" defaultValue={["email"]} aria-label="Channels"> <ToggleGroupItem value="email">Email</ToggleGroupItem> <ToggleGroupItem value="phone">Phone</ToggleGroupItem> <ToggleGroupItem value="imessage">iMessage</ToggleGroupItem> </ToggleGroup> );}export function Sizes() { return ( <div className="grid gap-3"> <ToggleGroup type="single" size="sm" defaultValue="left" aria-label="Alignment, small"> <ToggleGroupItem value="left" aria-label="Align left"> <TextAlignLeftIcon weight="bold" /> </ToggleGroupItem> <ToggleGroupItem value="center" aria-label="Align center"> <TextAlignCenterIcon weight="bold" /> </ToggleGroupItem> <ToggleGroupItem value="right" aria-label="Align right"> <TextAlignRightIcon weight="bold" /> </ToggleGroupItem> </ToggleGroup> <ToggleGroup type="single" spacing={0} defaultValue="day" aria-label="Range"> <ToggleGroupItem value="day">Day</ToggleGroupItem> <ToggleGroupItem value="week">Week</ToggleGroupItem> <ToggleGroupItem value="month">Month</ToggleGroupItem> <ToggleGroupItem value="year" disabled> Year </ToggleGroupItem> </ToggleGroup> <ToggleGroup type="single" orientation="vertical" defaultValue="inbox" aria-label="Folder" className="w-48"> <ToggleGroupItem value="inbox" className="justify-start">Inbox</ToggleGroupItem> <ToggleGroupItem value="sent" className="justify-start">Sent</ToggleGroupItem> <ToggleGroupItem value="spam" className="justify-start">Spam</ToggleGroupItem> </ToggleGroup> </div> );}Source
"use client";import * as React from "react";import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui";import { type VariantProps } from "class-variance-authority";import { toggleVariants } from "@/components/ui/toggle";import { cn } from "@/lib/utils";// The console's segmented choice (Figma 427:2715, Modal - Created: "Where does this agent run?"): a lilac track with// 10px corners and a 2px inset holding 38px choices 8px apart; each choice is a 24px logo tile 8px from a 14px medium// ink label, 8px from the sides, and the chosen one is a white key with 8px corners and Shadow/S. With `spacing={0}`// the choices sit flush in the track. `variant="outline"` drops the track: separate keys with the field edge, the chosen// one white with Shadow/S. Choosing is instant (no sliding key): the choice is made often and must feel immediate.const ToggleGroupContext = React.createContext<VariantProps<typeof toggleVariants> & { spacing?: number; orientation?: "horizontal" | "vertical" }>({ size: "default", variant: "default", spacing: 2, orientation: "horizontal",});function ToggleGroup({ className, variant = "default", size = "default", spacing = 2, orientation = "horizontal", children, ...props}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & VariantProps<typeof toggleVariants> & { spacing?: number; orientation?: "horizontal" | "vertical" }) { return ( <ToggleGroupPrimitive.Root data-slot="toggle-group" data-variant={variant} data-size={size} data-spacing={spacing} data-orientation={orientation} orientation={orientation} style={{ "--gap": spacing } as React.CSSProperties} className={cn( "group/toggle-group flex w-fit max-w-full items-center gap-[calc(var(--spacing)*var(--gap))] data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch", variant === "default" && "overflow-x-auto rounded-panel bg-subtle p-0.5 [scrollbar-width:none]", className, )} {...props} > <ToggleGroupContext.Provider value={{ variant, size, spacing, orientation }}>{children}</ToggleGroupContext.Provider> </ToggleGroupPrimitive.Root> );}function ToggleGroupItem({ className, children, variant, size, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleVariants>) { const context = React.useContext(ToggleGroupContext); const v = context.variant || variant || "default"; return ( <ToggleGroupPrimitive.Item data-slot="toggle-group-item" data-variant={v} data-size={context.size || size} data-spacing={context.spacing} className={cn( toggleVariants({ variant: v, size: context.size || size }), // In the track the chosen choice is the white key, as in the segmented choice. v === "default" && "hover:bg-subtle-hover data-[state=on]:bg-surface data-[state=on]:text-fg data-[state=on]:shadow-s data-[state=on]:hover:bg-surface", "focus-visible:z-10", className, )} {...props} > {children} </ToggleGroupPrimitive.Item> );}export { ToggleGroup, ToggleGroupItem };Reference: Figma 427:2715: Where does this agent run? in Modal - Created.