Skip to main content
Gremorie

Radio Group

Grupo de single-select de opções mutuamente exclusivas construído sobre o Radix RadioGroup, com roving tabindex e navegação por setas.

Visão geral

RadioGroup renderiza um conjunto de opções mutuamente exclusivas. Construído sobre @radix-ui/react-radio-group, a raiz é dona do valor selecionado e cada RadioGroupItem representa uma escolha. Limite as opções visíveis a cinco - além disso, prefira Select para eficiência de espaço vertical.

O primitivo do Radix cuida do padrão de roving tabindex (só a opção selecionada fica na ordem de tab) e da navegação por setas automaticamente. Você não precisa conectar onKeyDown ou tabIndex manualmente.

Preview

'use client';import { Label, RadioGroup, RadioGroupItem } from '@gremorie/rx-forms';export function RadioGroupPreview() {  return (    <RadioGroup defaultValue="react" className="flex flex-col gap-2">      <div className="flex items-center gap-2">        <RadioGroupItem id="rg-react" value="react" />        <Label htmlFor="rg-react">React</Label>      </div>      <div className="flex items-center gap-2">        <RadioGroupItem id="rg-ng" value="angular" />        <Label htmlFor="rg-ng">Angular</Label>      </div>      <div className="flex items-center gap-2">        <RadioGroupItem id="rg-both" value="both" />        <Label htmlFor="rg-both">Both</Label>      </div>    </RadioGroup>  );}

Anatomia

RadioGroup               the Root, a grid gap-3 owning the value
└─ RadioGroupItem        one circular option (value required); pair with a Label
   └─ Indicator          filled CircleIcon dot, shown only when selected

Instalação

bash npx gremorie@latest add rx-radio-group

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

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

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

Uso

import { Label, RadioGroup, RadioGroupItem } from "@gremorie/rx-forms";

export function Example() {
  return (
    <RadioGroup defaultValue="react">
      <div className="flex items-center gap-2">
        <RadioGroupItem id="rg-react" value="react" />
        <Label htmlFor="rg-react">React</Label>
      </div>
      <div className="flex items-center gap-2">
        <RadioGroupItem id="rg-ng" value="angular" />
        <Label htmlFor="rg-ng">Angular</Label>
      </div>
    </RadioGroup>
  );
}

A edição Angular deste componente hoje é distribuída a partir do source (veja o side-by-side no workbench); sua entrada no registry vem a seguir.

API

<RadioGroup>

PropTypeDefaultDescription
valuestring-Valor selecionado controlado.
defaultValuestring-Valor inicial não controlado.
onValueChange(value: string) => void-Dispara quando o usuário seleciona outra opção.
disabledbooleanfalseDesabilita o grupo inteiro.
requiredbooleanfalseMarca o grupo como obrigatório para envio de formulário.
namestring-Nome do campo de formulário.
orientation"horizontal" | "vertical""vertical"Afeta a direção da navegação por setas.
loopbooleantrueQuando true, as setas dão a volta da última para a primeira.

Encaminha para RadioGroupPrimitive.Root. Renderiza como um CSS Grid com gap-3 por default; sobrescreva className para layout customizado.

<RadioGroupItem>

PropTypeDefaultDescription
valuestring-O valor reportado de volta ao pai. Obrigatório.
disabledbooleanfalseDesabilita esta opção específica.

Renderiza um alvo circular com o indicador CircleIcon visível apenas quando selecionado. Carrega data-slot="radio-group-item".

Composição

  1. <RadioGroup> é o context raiz. Ele é dono do valor selecionado e da orientação.
  2. Cada <RadioGroupItem> é pareado com um <Label> via htmlFor correspondendo ao id do item. O label é o affordance que a maioria dos usuários clica.
  3. Para integração com formulário, envolva com <FormField> + <FormControl> para que o wiring de ARIA e a validação se propaguem.

Variações

Lista vertical (default)

O padrão canônico para 2-5 opções. Layout vertical facilita a leitura.

<RadioGroup defaultValue="monthly">
  <div className="flex items-center gap-2">
    <RadioGroupItem id="monthly" value="monthly" />
    <Label htmlFor="monthly">Monthly billing</Label>
  </div>
  <div className="flex items-center gap-2">
    <RadioGroupItem id="yearly" value="yearly" />
    <Label htmlFor="yearly">Yearly billing</Label>
  </div>
</RadioGroup>

Horizontal para labels curtos

Quando as opções são curtas e o context ao redor é largo o suficiente, mude para orientação horizontal.

<RadioGroup
  defaultValue="left"
  orientation="horizontal"
  className="flex flex-row gap-4"
>
  <div className="flex items-center gap-2">
    <RadioGroupItem id="left" value="left" />
    <Label htmlFor="left">Left</Label>
  </div>
  <div className="flex items-center gap-2">
    <RadioGroupItem id="center" value="center" />
    <Label htmlFor="center">Center</Label>
  </div>
  <div className="flex items-center gap-2">
    <RadioGroupItem id="right" value="right" />
    <Label htmlFor="right">Right</Label>
  </div>
</RadioGroup>

Com descrições

Adicione um parágrafo de hint após cada label quando a escolha tem consequências que valem explicar. Alinhe o item ao topo da linha com mt-0.5.

Balanced spacing for most layouts.

Roomier rows for dense data tables.

Tighter rows to fit more on screen.

'use client';import { Label, RadioGroup, RadioGroupItem } from '@gremorie/rx-forms';export function RadioGroupWithDescriptionPreview() {  return (    <RadioGroup defaultValue="comfortable">      <div className="flex items-start gap-3">        <RadioGroupItem value="default" id="rg-default" className="mt-0.5" />        <div className="grid gap-1">          <Label htmlFor="rg-default">Default</Label>          <p className="text-sm text-muted-foreground">            Balanced spacing for most layouts.          </p>        </div>      </div>      <div className="flex items-start gap-3">        <RadioGroupItem          value="comfortable"          id="rg-comfortable"          className="mt-0.5"        />        <div className="grid gap-1">          <Label htmlFor="rg-comfortable">Comfortable</Label>          <p className="text-sm text-muted-foreground">            Roomier rows for dense data tables.          </p>        </div>      </div>      <div className="flex items-start gap-3">        <RadioGroupItem value="compact" id="rg-compact" className="mt-0.5" />        <div className="grid gap-1">          <Label htmlFor="rg-compact">Compact</Label>          <p className="text-sm text-muted-foreground">            Tighter rows to fit more on screen.          </p>        </div>      </div>    </RadioGroup>  );}

Opção desabilitada

Desabilite um único RadioGroupItem para travar uma escolha indisponível enquanto mantém o resto do grupo interativo. Itens desabilitados são pulados durante a navegação por teclado.

'use client';import { Label, RadioGroup, RadioGroupItem } from '@gremorie/rx-forms';export function RadioGroupDisabledPreview() {  return (    <RadioGroup defaultValue="standard">      <div className="flex items-center gap-3">        <RadioGroupItem value="standard" id="rg-standard" />        <Label htmlFor="rg-standard">Standard shipping</Label>      </div>      <div className="flex items-center gap-3">        <RadioGroupItem value="express" id="rg-express" disabled />        <Label htmlFor="rg-express">Express (currently unavailable)</Label>      </div>      <div className="flex items-center gap-3">        <RadioGroupItem value="overnight" id="rg-overnight" />        <Label htmlFor="rg-overnight">Overnight</Label>      </div>    </RadioGroup>  );}

Acessibilidade

  • Padrão ARIA radiogroup: a raiz carrega role="radiogroup"; cada item carrega role="radio" com aria-checked refletindo o estado.
  • Roving tabindex: apenas o item selecionado (ou o primeiro, se nenhum estiver selecionado) fica na ordem de tab. Tab sai do grupo; as setas movem dentro dele.
  • Teclado:
    • ArrowDown / ArrowRight move para a próxima opção (e a seleciona).
    • ArrowUp / ArrowLeft move para a opção anterior.
    • Home / End pulam para o primeiro / último.
    • Space seleciona a opção em foco quando nenhuma está selecionada.
  • Loop: as setas dão a volta por default. Passe loop={false} se seu design espera comportamento de limite.
  • Itens desabilitados são pulados durante a navegação por teclado.

Relacionados

  • Checkbox - irmão de multi-select
  • Select - alternativa dropdown para listas mais longas
  • Toggle Group - single-select liderado por ícone para toolbars compactas
  • Label - o companheiro canônico
  • Form - conecte o RadioGroup no react-hook-form

On this page