Home / Docs / PixelToggleGroup PixelToggleGroup Grouped pressable toggles with single- or multi-select semantics, roving focus, and surface-aware styling.
Discriminated union API: type="single" → string value, type="multiple" → string[] value Optional roving tabindex with arrow-key navigation and Home/End support Single mode exposes radiogroup/radio semantics; multi mode uses aria-pressed buttons Surface-aware (pixel/linear) and supports soft, solid, outline, and ghost variants Status stable Category forms Since v1.9.0 API React Vue Angular
import { PixelToggleGroup } from '@pxlkit/ui-kit';Prop Type Default Description type'single' | 'multiple''single'single: one value, a radiogroup of radios; multiple: any number of values, pressed buttons.valuestring | string[]— Value: a string in single mode ('' for none), an array in multiple mode; leave unset for an uncontrolled group. defaultValuestring | string[]— Initial value while uncontrolled; nothing pressed by default. onChange((next: string) => void) | ((next: string[]) => void)— Called with the new value, after each press. rovingFocusbooleanfalseOnly one toggle is in the tab order; the arrow keys, Home and End move between them. loopbooleanfalseThe arrow keys wrap from the last toggle to the first and back. size'sm' | 'md' | 'lg''md'Size of the toggles. variant'solid' | 'soft' | 'ghost' | 'outline''soft'Variant of the toggles. surface'pixel' | 'linear'— Surface of the toggles; defaults to the nearest provider. aria-labelstring— Accessible label for the toolbar / radiogroup. children* (required) React.ReactNode— The PixelToggles.
Also takes the native attributes and event handlers of <div> (HTMLAttributes<HTMLDivElement>).
ref points to <div>.
Accessibility WCAG target: 2.1 AA
Provide an aria-label (or aria-labelledby) for screen reader context. Single-select renders role="radiogroup" with role="radio" children; multi-select renders role="group" only when named.
Keyboard Key Action When ArrowRight / ArrowDown Move focus to next item rovingFocus ArrowLeft / ArrowUp Move focus to previous item rovingFocus Home Move focus to first item rovingFocus End Move focus to last item rovingFocus Space / Enter Toggle the focused item —
Usage React Vue Angular
import { useState } from 'react';
import { PixelToggle, PixelToggleGroup } from '@pxlkit/ui-kit';
export function Default() {
const [value, setValue] = useState<string>('left');
return (
<PixelToggleGroup
type="single"
value={value}
onChange={setValue}
aria-label="Text alignment"
>
<PixelToggle value="left">Left</PixelToggle>
<PixelToggle value="center">Center</PixelToggle>
<PixelToggle value="right">Right</PixelToggle>
</PixelToggleGroup>
);
}Examples Default React Vue Angular
import { useState } from 'react';
import { PixelToggle, PixelToggleGroup } from '@pxlkit/ui-kit';
export function Default() {
const [value, setValue] = useState<string>('left');
return (
<PixelToggleGroup
type="single"
value={value}
onChange={setValue}
aria-label="Text alignment"
>
<PixelToggle value="left">Left</PixelToggle>
<PixelToggle value="center">Center</PixelToggle>
<PixelToggle value="right">Right</PixelToggle>
</PixelToggleGroup>
);
}Multiple React Vue Angular
import { useState } from 'react';
import { PixelToggle, PixelToggleGroup } from '@pxlkit/ui-kit';
export function Multiple() {
const [value, setValue] = useState<string[]>(['bold']);
return (
<PixelToggleGroup
type="multiple"
value={value}
onChange={setValue}
aria-label="Text formatting"
>
<PixelToggle value="bold">Bold</PixelToggle>
<PixelToggle value="italic">Italic</PixelToggle>
<PixelToggle value="underline">Underline</PixelToggle>
</PixelToggleGroup>
);
}Variants React Vue Angular
import { useState } from 'react';
import { PixelToggle, PixelToggleGroup } from '@pxlkit/ui-kit';
export function Variants() {
const [a, setA] = useState<string>('one');
const [b, setB] = useState<string>('one');
const [c, setC] = useState<string>('one');
const [d, setD] = useState<string>('one');
return (
<div className="space-y-3">
<PixelToggleGroup type="single" variant="soft" value={a} onChange={setA} aria-label="Soft">
<PixelToggle value="one">One</PixelToggle>
<PixelToggle value="two">Two</PixelToggle>
<PixelToggle value="three">Three</PixelToggle>
</PixelToggleGroup>
<PixelToggleGroup type="single" variant="solid" value={b} onChange={setB} aria-label="Solid">
<PixelToggle value="one">One</PixelToggle>
<PixelToggle value="two">Two</PixelToggle>
<PixelToggle value="three">Three</PixelToggle>
</PixelToggleGroup>
<PixelToggleGroup type="single" variant="outline" value={c} onChange={setC} aria-label="Outline">
<PixelToggle value="one">One</PixelToggle>
<PixelToggle value="two">Two</PixelToggle>
<PixelToggle value="three">Three</PixelToggle>
</PixelToggleGroup>
<PixelToggleGroup type="single" variant="ghost" value={d} onChange={setD} aria-label="Ghost">
<PixelToggle value="one">One</PixelToggle>
<PixelToggle value="two">Two</PixelToggle>
<PixelToggle value="three">Three</PixelToggle>
</PixelToggleGroup>
</div>
);
}Sizes React Vue Angular
import { useState } from 'react';
import { PixelToggle, PixelToggleGroup } from '@pxlkit/ui-kit';
export function Sizes() {
const [sm, setSm] = useState<string>('a');
const [md, setMd] = useState<string>('a');
const [lg, setLg] = useState<string>('a');
return (
<div className="space-y-3">
<PixelToggleGroup type="single" size="sm" value={sm} onChange={setSm} aria-label="Small">
<PixelToggle value="a">A</PixelToggle>
<PixelToggle value="b">B</PixelToggle>
<PixelToggle value="c">C</PixelToggle>
</PixelToggleGroup>
<PixelToggleGroup type="single" size="md" value={md} onChange={setMd} aria-label="Medium">
<PixelToggle value="a">A</PixelToggle>
<PixelToggle value="b">B</PixelToggle>
<PixelToggle value="c">C</PixelToggle>
</PixelToggleGroup>
<PixelToggleGroup type="single" size="lg" value={lg} onChange={setLg} aria-label="Large">
<PixelToggle value="a">A</PixelToggle>
<PixelToggle value="b">B</PixelToggle>
<PixelToggle value="c">C</PixelToggle>
</PixelToggleGroup>
</div>
);
}Roving focus React Vue Angular
import { useState } from 'react';
import { PixelToggle, PixelToggleGroup } from '@pxlkit/ui-kit';
export function RovingFocus() {
const [value, setValue] = useState<string>('list');
return (
<PixelToggleGroup
type="single"
rovingFocus
loop
value={value}
onChange={setValue}
aria-label="View mode"
>
<PixelToggle value="list">List</PixelToggle>
<PixelToggle value="grid">Grid</PixelToggle>
<PixelToggle value="board">Board</PixelToggle>
</PixelToggleGroup>
);
}Surfaces React Vue Angular
import { useState } from 'react';
import { PixelToggle, PixelToggleGroup } from '@pxlkit/ui-kit';
export function Surfaces() {
const [pixel, setPixel] = useState<string>('one');
const [linear, setLinear] = useState<string>('one');
return (
<div className="space-y-3">
<PixelToggleGroup
type="single"
surface="pixel"
value={pixel}
onChange={setPixel}
aria-label="Pixel surface"
>
<PixelToggle value="one">One</PixelToggle>
<PixelToggle value="two">Two</PixelToggle>
</PixelToggleGroup>
<PixelToggleGroup
type="single"
surface="linear"
value={linear}
onChange={setLinear}
aria-label="Linear surface"
>
<PixelToggle value="one">One</PixelToggle>
<PixelToggle value="two">Two</PixelToggle>
</PixelToggleGroup>
</div>
);
}