Shadwire
Componentes

Radio Group

Um conjunto de opções mutuamente exclusivas, construído sobre radios nativos.

Instalação

O Shadwire segue o modelo open-code do shadcn/ui: o código-fonte do componente é copiado para a sua aplicação e passa a ser seu. Instale com a CLI:

shadwire add radio-group --yes

O item radio-group do registry instala estes arquivos:

  • app/components/ui_component.rb
  • app/components/ui/radio_group_component.rb
  • app/components/ui/radio_group/item_component.rb
  • app/helpers/ui/radio_group_helper.rb
  • vendor/shadwire/shadwire.css

Ainda não instalou a CLI? gem install shadwire e depois shadwire init.

Uso

Itens com o mesmo name: formam o grupo — seleção única e navegação por setas vêm do navegador. Rotule o grupo com aria: { label: }.

<%= ui_radio_group(aria: { label: "Plano" }) do %>
  <div class="flex items-center gap-2">
    <%= ui_radio_group_item(name: "plan", value: "free", id: "plan-free", checked: true) %>
    <%= ui_label(for: "plan-free") { "Gratuito" } %>
  </div>
<% end %>

Ou renderize os componentes diretamente:

<%= render Ui::RadioGroupComponent.new do %>
  <%= render Ui::RadioGroup::ItemComponent.new(name: "plan", value: "free") %>
<% end %>

Composição

Cada item é um <input type="radio"> nativo; o name: é repetido por item porque o ViewComponent não injeta contexto do pai.

RadioGroup
`-- RadioGroup::Item (um por opção, mesmo name:)

Exemplos

Padrão

Radios nativos compartilhando o mesmo name: — a navegação por setas vem do navegador.

<%= ui_radio_group(aria: { label: "Densidade da interface" }) do %>
  <div class="flex items-center gap-2">
    <%= ui_radio_group_item(name: "density", value: "default", id: "density-default", checked: true) %>
    <%= ui_label(for: "density-default") { "Padrão" } %>
  </div>
  <div class="flex items-center gap-2">
    <%= ui_radio_group_item(name: "density", value: "comfortable", id: "density-comfortable") %>
    <%= ui_label(for: "density-comfortable") { "Confortável" } %>

Item desabilitado

disabled: true desabilita um item específico sem afetar o grupo.

<%= ui_radio_group(aria: { label: "Plano" }) do %>
  <div class="flex items-center gap-2">
    <%= ui_radio_group_item(name: "plan", value: "free", id: "plan-free", checked: true) %>
    <%= ui_label(for: "plan-free") { "Gratuito" } %>
  </div>
  <div class="flex items-center gap-2">
    <%= ui_radio_group_item(name: "plan", value: "enterprise", id: "plan-enterprise", disabled: true) %>
    <%= ui_label(for: "plan-enterprise", class: "opacity-50") { "Enterprise (em breve)" } %>

Com form_with

Use form.field_name para o name compartilhado e form.field_id(attr, valor) para cada id.

<%= form_with url: "#", scope: :subscription do |form| %>
  <%= ui_radio_group(aria: { label: "Ciclo de cobrança" }) do %>
    <div class="flex items-center gap-2">
      <%= ui_radio_group_item(
            name: form.field_name(:cycle),
            value: "monthly",
            id: form.field_id(:cycle, "monthly"),
            checked: true

Referência da API

ui_radio_group(**options, &block) e ui_radio_group_item(**options) encapsulam os componentes correspondentes.

Componente Argumento Padrão Descrição
RadioGroup class / class_name, **attrs Container role="radiogroup"; rotule com aria: { label: }.
RadioGroup::Item name: (obrigatório) Nome compartilhado do grupo de radios.
RadioGroup::Item value: (obrigatório) Valor submetido quando o item está selecionado.
RadioGroup::Item checked / disabled false Estado inicial do input nativo.
RadioGroup::Item **attrs {} Atributos HTML livres (id, data:, aria:, …).