Skip to main content
Gremorie

Toggle Group

Cluster coordenado de Toggles - tipo radio com `type="single"` ou tipo checkbox com `type="multiple"`, com sizing e variant compartilhados via context.

Visão geral

ToggleGroup é um conjunto coordenado de buttons estilo Toggle. Use type="single" para comportamento tipo radio (um pressionado por vez) ou type="multiple" para tipo checkbox (qualquer número pressionado). Tamanhos e variants propagam da raiz para cada ToggleGroupItem via context, então o cluster sempre parece coerente.

Use ToggleGroup para estado de formatação e visualização (alinhamento de texto, modo de visualização, filter chips) - liderado por ícone, efeito visual imediato. RadioGroup é para valores de formulário (liderado por label, capturado no submit); Tabs trocam painéis de conteúdo inteiros em vez de aplicar um estado.

Preview

'use client';import { ToggleGroup, ToggleGroupItem } from '@gremorie/rx-forms';import { Bold, Italic, Underline } from 'lucide-react';export function ToggleGroupPreview() {  return (    <ToggleGroup type="single" defaultValue="bold">      <ToggleGroupItem value="bold" aria-label="Bold">        <Bold className="size-4" />      </ToggleGroupItem>      <ToggleGroupItem value="italic" aria-label="Italic">        <Italic className="size-4" />      </ToggleGroupItem>      <ToggleGroupItem value="underline" aria-label="Underline">        <Underline className="size-4" />      </ToggleGroupItem>    </ToggleGroup>  );}

Anatomia

ToggleGroup                 o Root; é dono de type, variant, size, spacing e os compartilha via context
└─ ToggleGroupItem          um toggle button; herda a estilização do Root

Instalação

bash npx gremorie@latest add rx-toggle-group

bash pnpm dlx gremorie@latest add rx-toggle-group

bash yarn dlx gremorie@latest add rx-toggle-group

bash bunx --bun gremorie@latest add rx-toggle-group

Uso

import { ToggleGroup, ToggleGroupItem } from "@gremorie/rx-forms";
import { Bold, Italic, Underline } from "lucide-react";

export function Example() {
  return (
    <ToggleGroup type="single" defaultValue="bold">
      <ToggleGroupItem value="bold" aria-label="Bold">
        <Bold />
      </ToggleGroupItem>
      <ToggleGroupItem value="italic" aria-label="Italic">
        <Italic />
      </ToggleGroupItem>
      <ToggleGroupItem value="underline" aria-label="Underline">
        <Underline />
      </ToggleGroupItem>
    </ToggleGroup>
  );
}

A edição Angular deste componente hoje é entregue a partir do código-fonte (veja o workbench para o comparativo lado a lado); a entrada de registry vem em seguida.

API

<ToggleGroup>

PropTypeDefaultDescription
type"single" | "multiple"-single força um item pressionado; multiple permite qualquer número. Obrigatório.
valuestring | string[]-Valor controlado. String única para type="single", array para type="multiple".
defaultValuestring | string[]-Valor inicial não controlado.
onValueChange(value: string | string[]) => void-Dispara quando a seleção muda.
disabledbooleanfalseDesabilita o grupo inteiro.
variant"default" | "outline""default"Encaminhado para cada item via context.
size"default" | "sm" | "lg""default"Encaminhado para cada item via context.
spacingnumber0Gap entre itens em unidades de spacing. 0 os une com uma borda compartilhada (estilo button-group); valores positivos os separam em buttons distintos.
rovingFocusbooleantrueHabilita roving tabindex (default do Radix).
loopbooleantrueSetas dão a volta.

Encaminha para ToggleGroupPrimitive.Root. Envolve os filhos em um ToggleGroupContext interno para que ToggleGroupItem herde variant, size e spacing.

<ToggleGroupItem>

PropTypeDefaultDescription
valuestring-O valor reportado de volta ao pai. Obrigatório.
disabledbooleanfalseDesabilita este item específico.
variant"default" | "outline"herdado do grupoSobrescreve a variant do grupo para este item. Raro.
size"default" | "sm" | "lg"herdado do grupoSobrescreve o size do grupo para este item. Raro.

O item lê de ToggleGroupContext antes de recorrer às suas próprias props, então o grupo sempre vence a menos que explicitamente sobrescrito.

Composição

  1. <ToggleGroup> é o context raiz. Defina type, variant, size e spacing uma vez.
  2. <ToggleGroupItem> sempre dentro de <ToggleGroup> - ele depende do context para a estilização.
  3. Os filhos são tipicamente ícones. Para texto + ícone, siga o padrão do Button.
  4. spacing={0} (default) une os itens com uma borda compartilhada como ButtonGroup. spacing positivo os mantém como buttons distintos com gaps.

Variações

Formatação de texto (single)

O padrão canônico. type="single" para comportamento tipo radio.

import { AlignLeft, AlignCenter, AlignRight } from 'lucide-react';

<ToggleGroup type="single" defaultValue="left">
  <ToggleGroupItem value="left" aria-label="Align left">
    <AlignLeft />
  </ToggleGroupItem>
  <ToggleGroupItem value="center" aria-label="Align center">
    <AlignCenter />
  </ToggleGroupItem>
  <ToggleGroupItem value="right" aria-label="Align right">
    <AlignRight />
  </ToggleGroupItem>
</ToggleGroup>;

Formatação multi-select

type="multiple" deixa os usuários pressionarem múltiplos itens (ex. bold + italic ao mesmo tempo).

'use client';import { ToggleGroup, ToggleGroupItem } from '@gremorie/rx-forms';import { Bold, Italic, Underline } from 'lucide-react';export function ToggleGroupMultiplePreview() {  return (    <ToggleGroup type="multiple" defaultValue={['bold']}>      <ToggleGroupItem value="bold" aria-label="Bold">        <Bold />      </ToggleGroupItem>      <ToggleGroupItem value="italic" aria-label="Italic">        <Italic />      </ToggleGroupItem>      <ToggleGroupItem value="underline" aria-label="Underline">        <Underline />      </ToggleGroupItem>    </ToggleGroup>  );}

Variant outline com spacing

Quando o cluster deve ser lido como uma row de buttons independentes em vez de uma unidade unida, use variant="outline" mais um valor positivo de spacing.

'use client';import { ToggleGroup, ToggleGroupItem } from '@gremorie/rx-forms';import { LayoutGrid, List, Rows3 } from 'lucide-react';export function ToggleGroupOutlinePreview() {  return (    <ToggleGroup      type="single"      defaultValue="grid"      variant="outline"      spacing={1}    >      <ToggleGroupItem value="list" aria-label="List view">        <List />      </ToggleGroupItem>      <ToggleGroupItem value="grid" aria-label="Grid view">        <LayoutGrid />      </ToggleGroupItem>      <ToggleGroupItem value="board" aria-label="Board view">        <Rows3 />      </ToggleGroupItem>    </ToggleGroup>  );}

Tamanhos

A prop size definida na raiz propaga para cada item via context, então o cluster inteiro escala junto. Os presets disponíveis são sm, default e lg.

'use client';import { ToggleGroup, ToggleGroupItem } from '@gremorie/rx-forms';import { AlignCenter, AlignLeft, AlignRight } from 'lucide-react';export function ToggleGroupSizesPreview() {  return (    <div className="flex flex-col items-start gap-3">      <ToggleGroup type="single" defaultValue="left" size="sm">        <ToggleGroupItem value="left" aria-label="Align left">          <AlignLeft />        </ToggleGroupItem>        <ToggleGroupItem value="center" aria-label="Align center">          <AlignCenter />        </ToggleGroupItem>        <ToggleGroupItem value="right" aria-label="Align right">          <AlignRight />        </ToggleGroupItem>      </ToggleGroup>      <ToggleGroup type="single" defaultValue="left" size="default">        <ToggleGroupItem value="left" aria-label="Align left">          <AlignLeft />        </ToggleGroupItem>        <ToggleGroupItem value="center" aria-label="Align center">          <AlignCenter />        </ToggleGroupItem>        <ToggleGroupItem value="right" aria-label="Align right">          <AlignRight />        </ToggleGroupItem>      </ToggleGroup>      <ToggleGroup type="single" defaultValue="left" size="lg">        <ToggleGroupItem value="left" aria-label="Align left">          <AlignLeft />        </ToggleGroupItem>        <ToggleGroupItem value="center" aria-label="Align center">          <AlignCenter />        </ToggleGroupItem>        <ToggleGroupItem value="right" aria-label="Align right">          <AlignRight />        </ToggleGroupItem>      </ToggleGroup>    </div>  );}

Seleção controlada

Controle o cluster a partir de estado externo - útil para filter chips ancorados em URL search params.

function FilterChips() {
  const [filters, setFilters] = React.useState<string[]>([]);
  return (
    <ToggleGroup
      type="multiple"
      value={filters}
      onValueChange={setFilters}
      variant="outline"
    >
      <ToggleGroupItem value="open">Open</ToggleGroupItem>
      <ToggleGroupItem value="closed">Closed</ToggleGroupItem>
      <ToggleGroupItem value="merged">Merged</ToggleGroupItem>
    </ToggleGroup>
  );
}

Acessibilidade

  • Semântica de grupo: renderizado com role="group". Os itens carregam o role="radio" apropriado (para type="single") ou role="button" com aria-pressed (para type="multiple").
  • Roving tabindex: apenas um item está na ordem de tabulação por vez. Tab sai do grupo; as setas navegam dentro.
  • Teclado:
    • Tab entra e sai do grupo.
    • ArrowLeft / ArrowRight (ou ArrowUp / ArrowDown) navegam entre os itens.
    • Home / End saltam para o primeiro / último.
    • Space / Enter alternam o item focado.
  • Loop: as setas dão a volta por padrão. Passe loop={false} para desabilitar.
  • Itens icon-only: sempre forneça aria-label em cada item. O próprio grupo também pode carregar aria-label para nomear o cluster inteiro.

Relacionados

  • Toggle - o primitive de button único subjacente
  • Button Group - primo visual sem estado coordenado
  • Radio Group - single-select liderado por label para valores de formulário
  • Tabs - troca painéis de conteúdo inteiros (modelo mental diferente)

On this page