Skip to main content

Toggle Group

A group of toggle buttons where one or multiple items can be active at a time.

import * as ToggleGroup from '@gentleduck/primitives/toggle-group'
import * as ToggleGroup from '@gentleduck/primitives/toggle-group'

Anatomy

<ToggleGroup.Root>
  <ToggleGroup.Item />
</ToggleGroup.Root>
<ToggleGroup.Root>
  <ToggleGroup.Item />
</ToggleGroup.Root>

Example

Single selection

import * as ToggleGroup from '@gentleduck/primitives/toggle-group'
import { AlignLeft, AlignCenter, AlignRight } from 'lucide-react'
 
function TextAlign() {
  return (
    <ToggleGroup.Root type="single" defaultValue="left" className="flex gap-1">
      <ToggleGroup.Item value="left" aria-label="Align left" className="rounded p-2 data-[state=on]:bg-accent">
        <AlignLeft className="size-4" />
      </ToggleGroup.Item>
      <ToggleGroup.Item value="center" aria-label="Align center" className="rounded p-2 data-[state=on]:bg-accent">
        <AlignCenter className="size-4" />
      </ToggleGroup.Item>
      <ToggleGroup.Item value="right" aria-label="Align right" className="rounded p-2 data-[state=on]:bg-accent">
        <AlignRight className="size-4" />
      </ToggleGroup.Item>
    </ToggleGroup.Root>
  )
}
import * as ToggleGroup from '@gentleduck/primitives/toggle-group'
import { AlignLeft, AlignCenter, AlignRight } from 'lucide-react'
 
function TextAlign() {
  return (
    <ToggleGroup.Root type="single" defaultValue="left" className="flex gap-1">
      <ToggleGroup.Item value="left" aria-label="Align left" className="rounded p-2 data-[state=on]:bg-accent">
        <AlignLeft className="size-4" />
      </ToggleGroup.Item>
      <ToggleGroup.Item value="center" aria-label="Align center" className="rounded p-2 data-[state=on]:bg-accent">
        <AlignCenter className="size-4" />
      </ToggleGroup.Item>
      <ToggleGroup.Item value="right" aria-label="Align right" className="rounded p-2 data-[state=on]:bg-accent">
        <AlignRight className="size-4" />
      </ToggleGroup.Item>
    </ToggleGroup.Root>
  )
}

Multiple selection

function FormatOptions() {
  return (
    <ToggleGroup.Root type="multiple" className="flex gap-1">
      <ToggleGroup.Item value="bold" className="rounded p-2 data-[state=on]:bg-accent">B</ToggleGroup.Item>
      <ToggleGroup.Item value="italic" className="rounded p-2 data-[state=on]:bg-accent">I</ToggleGroup.Item>
      <ToggleGroup.Item value="underline" className="rounded p-2 data-[state=on]:bg-accent">U</ToggleGroup.Item>
    </ToggleGroup.Root>
  )
}
function FormatOptions() {
  return (
    <ToggleGroup.Root type="multiple" className="flex gap-1">
      <ToggleGroup.Item value="bold" className="rounded p-2 data-[state=on]:bg-accent">B</ToggleGroup.Item>
      <ToggleGroup.Item value="italic" className="rounded p-2 data-[state=on]:bg-accent">I</ToggleGroup.Item>
      <ToggleGroup.Item value="underline" className="rounded p-2 data-[state=on]:bg-accent">U</ToggleGroup.Item>
    </ToggleGroup.Root>
  )
}

API

ToggleGroup.Root

The root container. Renders a <div>. Supports two modes: single and multiple.

Single mode

PropTypeDefaultDescription
type'single'--Only one item can be active
valuestring--Controlled active value
defaultValuestring--Initial active value
onValueChange(value: string) => void--Called when active value changes

Multiple mode

PropTypeDefaultDescription
type'multiple'--Multiple items can be active
valuestring[]--Controlled active values
defaultValuestring[]--Initial active values
onValueChange(value: string[]) => void--Called when active values change

Shared props

PropTypeDefaultDescription
rovingFocusbooleantrueEnable roving focus keyboard navigation
disabledbooleanfalseDisables the entire group
orientation'horizontal' | 'vertical'--Arrow key navigation direction
dir'ltr' | 'rtl'--Text direction
loopbooleantrueKeyboard navigation wraps around
asChildboolean--Render as child element

Exposes data-orientation attribute.

ToggleGroup.Item

An individual toggle button within the group. Renders a <button>.

PropTypeDefaultDescription
valuestring--Required. Unique value for this item
disabledboolean--Disables this item (inherits from group)
asChildboolean--Render as child element

Exposes aria-pressed (multiple mode), role="radio" (single mode), data-state (on | off), and data-disabled attributes.


Keyboard interactions

KeyAction
TabMoves focus into the group and to the active item
ArrowRightMoves focus to the next item (horizontal)
ArrowLeftMoves focus to the previous item (horizontal)
ArrowDownMoves focus to the next item (vertical)
ArrowUpMoves focus to the previous item (vertical)
HomeMoves focus to the first item
EndMoves focus to the last item
Space / EnterToggles the focused item