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 selectedInstalaçã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>
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | Valor selecionado controlado. |
defaultValue | string | - | Valor inicial não controlado. |
onValueChange | (value: string) => void | - | Dispara quando o usuário seleciona outra opção. |
disabled | boolean | false | Desabilita o grupo inteiro. |
required | boolean | false | Marca o grupo como obrigatório para envio de formulário. |
name | string | - | Nome do campo de formulário. |
orientation | "horizontal" | "vertical" | "vertical" | Afeta a direção da navegação por setas. |
loop | boolean | true | Quando 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>
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | O valor reportado de volta ao pai. Obrigatório. |
disabled | boolean | false | Desabilita 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
<RadioGroup>é o context raiz. Ele é dono do valor selecionado e da orientação.- Cada
<RadioGroupItem>é pareado com um<Label>viahtmlForcorrespondendo aoiddo item. O label é o affordance que a maioria dos usuários clica. - 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 carregarole="radio"comaria-checkedrefletindo o estado. - Roving tabindex: apenas o item selecionado (ou o primeiro, se nenhum estiver selecionado) fica na ordem de tab.
Tabsai do grupo; as setas movem dentro dele. - Teclado:
ArrowDown/ArrowRightmove para a próxima opção (e a seleciona).ArrowUp/ArrowLeftmove para a opção anterior.Home/Endpulam para o primeiro / último.Spaceseleciona 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