Pho Design System

Toggle Group

Groups related Toggle buttons into one control with shared roving-focus keyboard navigation — text alignment, view mode, formatting clusters. Built on Base UI ToggleGroup.

Import

import { ToggleGroup } from "@photon-ai/pho-ui/components/toggle-group";
import { Toggle } from "@photon-ai/pho-ui/components/toggle";

Basic

Single-select by default — one item pressed at a time; pressing another releases the first. Each Toggle carries a value; track selection with value / onValueChange (an array) or defaultValue.

import {
  IconAlignLeft,
  IconAlignCenter,
  IconAlignRight,
} from "@tabler/icons-react";

<ToggleGroup defaultValue={["left"]}>
  <Toggle value="left" aria-label="Align left">
    <IconAlignLeft />
  </Toggle>
  <Toggle value="center" aria-label="Align center">
    <IconAlignCenter />
  </Toggle>
  <Toggle value="right" aria-label="Align right">
    <IconAlignRight />
  </Toggle>
</ToggleGroup>;

Multiple

Set multiple when several items can be pressed at once — a formatting cluster where Bold, Italic, and Underline stack. The value is still an array; it simply holds every pressed item.

import { IconBold, IconItalic, IconUnderline } from "@tabler/icons-react";

<ToggleGroup multiple defaultValue={["bold"]}>
  <Toggle value="bold" aria-label="Bold">
    <IconBold />
  </Toggle>
  <Toggle value="italic" aria-label="Italic">
    <IconItalic />
  </Toggle>
  <Toggle value="underline" aria-label="Underline">
    <IconUnderline />
  </Toggle>
</ToggleGroup>;

Controlled

Pass value and onValueChange to own the selection — the callback hands back the pressed-values array, so read value[0] for a single-select group and the whole array when multiple. Use defaultValue instead for the initial value only.

Aligned left
const [value, setValue] = useState<string[]>(["left"]);

<ToggleGroup value={value} onValueChange={setValue}>
  {/* …toggles… */}
</ToggleGroup>;

Orientation

orientation="vertical" stacks the group and swaps the arrow-key axis to Up/Down. It sets data-orientation for styling; lay the items out in a column yourself (here, className="flex-col").

<ToggleGroup
  orientation="vertical"
  defaultValue={["left"]}
  className="flex-col"
>
  {/* …toggles… */}
</ToggleGroup>

Disabled

disabled on the group ignores interaction across every item and dims the whole control; the current selection stays visible.

<ToggleGroup defaultValue={["center"]} disabled>
  {/* …toggles… */}
</ToggleGroup>

Anatomy

Props

Each child Toggle takes its own value (required) and a size of sm · md · lg (default md) — see the Toggle page.

Accessibility

Keyboard: the group is a single tab stop (roving tabindex).

Best practices