Toggle
A two-state button that stays pressed — the canonical Bold / Italic formatting
control. Built on Base UI Toggle, which manages the pressed state and
aria-pressed. For a set of related toggles (alignment, view mode), use
ToggleGroup; for an on/off setting, use Switch.
Import
import { Toggle } from "@photon-ai/pho-ui/components/toggle";
Basic
Each toggle is icon-only and needs an aria-label. Use defaultPressed for an
initial on state. The pressed toggle renders as the inverted chip (the site’s
Tab-active fill); disabled dims to 50%.
import { IconBold, IconItalic } from "@tabler/icons-react";
<Toggle aria-label="Bold">
<IconBold weight="bold" />
</Toggle>
<Toggle aria-label="Italic" defaultPressed>
<IconItalic />
</Toggle>
Sizes
Three square sizes — sm, md, lg — sized to sit in a toolbar next to
inputs. The default is md.
<Toggle size="sm" aria-label="Bold"><IconBold weight="bold" /></Toggle>
<Toggle size="md" aria-label="Bold"><IconBold weight="bold" /></Toggle>
<Toggle size="lg" aria-label="Bold"><IconBold weight="bold" /></Toggle>
Controlled
Pass pressed and onPressedChange to own the state — read it back to swap the
icon, persist the choice, or drive other UI off it.
import { IconStar } from "@tabler/icons-react";
const [pressed, setPressed] = useState(false);
<Toggle
aria-label="Add to favorites"
pressed={pressed}
onPressedChange={setPressed}
>
<IconStar weight={pressed ? "fill" : "regular"} />
</Toggle>;
Props
Beyond these, Toggle forwards native <button> attributes and className.
- size —
"sm"·"md"·"lg"(defaultmd) - pressed —
boolean— controlled pressed state - defaultPressed —
boolean— uncontrolled initial state (defaultfalse) - onPressedChange —
(pressed, eventDetails) => void— fires on toggle - disabled —
boolean— non-interactive, dimmed (defaultfalse) - value —
string— identifies the toggle inside aToggleGroup - aria-label —
string(required) — names the action; the control is icon-only
Accessibility
Toggle renders a native <button> with aria-pressed reflecting the state
(mirrored as data-pressed for styling, data-disabled when off-limits).
Because it carries only an icon, an aria-label naming the action is required —
without it the control is unlabelled to screen readers.
Keyboard:
- Space / Enter toggle the pressed state (native button behavior).
- Tab moves focus to and from the toggle.
Focus is shown with the pho-brand focus-visible ring. State is announced
through aria-pressed, so no live region is needed.
Best practices
- A
Toggleis the right control when pressing it changes the appearance of a selection (bold text), not a saved setting — reach forSwitchfor the latter. - Toggles are icon-only here, so an
aria-labelis mandatory; name the action (Bold), not the icon. - Group mutually-related toggles with
ToggleGroupso selection and keyboard navigation behave as one control.