Qure UI
Components

Toggle Group

A row of Toggles sharing one pressed state, with arrow-key focus.

'use client'import { Toggle } from '@/registry/qure/ui/toggle'import { ToggleGroup } from '@/registry/qure/ui/toggle-group'export default function ToggleGroupDemo() {  return (    <ToggleGroup defaultValue={['axial']} aria-label="Reconstruction plane">      <Toggle value="axial" size="sm">Axial</Toggle>      <Toggle value="coronal" size="sm">Coronal</Toggle>      <Toggle value="sagittal" size="sm">Sagittal</Toggle>    </ToggleGroup>  )}

Installation

npx shadcn@latest add https://qure-ui.qure.ai/r/toggle-group.json

Usage

import { ToggleGroup } from '@/components/ui/toggle-group'
import { Toggle } from '@/components/ui/toggle'
<ToggleGroup defaultValue={['axial']} aria-label="Reconstruction plane">
  <Toggle value="axial" size="sm">Axial</Toggle>
  <Toggle value="coronal" size="sm">Coronal</Toggle>
  <Toggle value="sagittal" size="sm">Sagittal</Toggle>
</ToggleGroup>

Every child needs a value — that is what the group's array holds. defaultValue and value are arrays even when only one button can be pressed.

multiple defaults to false, so a plain ToggleGroup behaves as a segmented choice: press one and the others release. That is the same name and the same default as Accordion's, and it is the opposite of what a row of independent-looking buttons suggests. If the buttons are overlays rather than alternatives, you have to say multiple.

Composition

<ToggleGroup>          {/* the shared value, roving focus, orientation */}
  <Toggle value="…" /> {/* an ordinary Toggle; the group takes over its state */}
</ToggleGroup>

A Toggle inside a group is the same component as one outside it. It stops owning its own pressed state and reads the group's instead, which is why value becomes required.

Variants

tray — the default — puts a tinted surface behind the buttons, and the pressed one lifts onto the page's own background. That is the segmented-control reading, and the one to use when the buttons are alternatives.

'use client'import { Toggle } from '@/registry/qure/ui/toggle'import { ToggleGroup } from '@/registry/qure/ui/toggle-group'export default function ToggleGroupPlain() {  return (    <ToggleGroup      variant="plain"      multiple      defaultValue={['ct']}      aria-label="Modalities on the worklist"    >      <Toggle value="ct" variant="outline" size="sm">CT</Toggle>      <Toggle value="cxr" variant="outline" size="sm">CXR</Toggle>      <Toggle value="mri" variant="outline" size="sm">MRI</Toggle>      <Toggle value="us" variant="outline" size="sm" disabled>US</Toggle>    </ToggleGroup>  )}

plain is just a row with a gap, for buttons that happen to share state without being a single choice. Pair it with variant="outline" on the toggles so each keeps its own edge.

Several at once

'use client'import { CrosshairIcon, LayersIcon, RulerIcon } from 'lucide-react'import { Toggle } from '@/registry/qure/ui/toggle'import { ToggleGroup } from '@/registry/qure/ui/toggle-group'export default function ToggleGroupMultiple() {  return (    <ToggleGroup multiple defaultValue={['heatmap', 'measurements']} aria-label="Viewer overlays">      <Toggle value="heatmap" size="sm">        <LayersIcon />        Heatmap      </Toggle>      <Toggle value="measurements" size="sm">        <RulerIcon />        Measurements      </Toggle>      <Toggle value="localisers" size="sm">        <CrosshairIcon />        Localisers      </Toggle>    </ToggleGroup>  )}

multiple for overlays, filters, anything where the answer is a set rather than a choice. A worklist's modality filter and a viewer's overlay switches are both this shape.

Icons only

'use client'import { Columns3Icon, Grid2x2Icon, SquareDashedIcon } from 'lucide-react'import { Toggle } from '@/registry/qure/ui/toggle'import { ToggleGroup } from '@/registry/qure/ui/toggle-group'export default function ToggleGroupIcons() {  return (    <ToggleGroup defaultValue={['1x1']} aria-label="Hanging protocol">      <Toggle value="1x1" size="sm" iconOnly aria-label="Single pane">        <SquareDashedIcon />      </Toggle>      <Toggle value="1x2" size="sm" iconOnly aria-label="Two panes, side by side">        <Columns3Icon />      </Toggle>      <Toggle value="2x2" size="sm" iconOnly aria-label="Four panes">        <Grid2x2Icon />      </Toggle>    </ToggleGroup>  )}

iconOnly squares each button. Every one still needs an aria-label, and the group needs one too — a hanging-protocol picker announced as three unnamed pressed buttons is unusable.

Keyboard

Arrow keys move between buttons and Tab leaves the group, because the group is one stop rather than three. loopFocus (default true) wraps at the ends; turn it off when the group is long enough that wrapping would be disorienting.

API Reference

Everything Base UI's Toggle Group accepts, plus:

Prop

Type

And from Base UI:

Prop

Type

On this page