Formularios

Estado: Beta

Tarjetas de opción

Radios nativos con forma de tarjeta para elegir entre pocas opciones que necesitan contexto: entrega, método de pago, plan. Cada tarjeta lleva título, descripción, un dato a la derecha (precio, tiempo) e ícono opcional. Al elegir, el marco del acento viaja con resorte a la nueva y su círculo se llena.

Entrega

app/views/… (la demo de arriba)

<%# Las opciones de un pedido en el checkout: entrega y método de pago.
    En la tarjeta del índice solo se ve la entrega; en el escenario, también el pago. %>
<div class="@container w-full max-w-2xl">
  <div class="grid gap-8">
    <%= render Ui::RadioCardsComponent.new(name: "order[delivery_method]", id: "radio-cards-demo-delivery", label: "Entrega",
                                           selected: "shipping", required: true,
                                           options: [
                                             { value: "shipping", title: "Envío a domicilio", description: "Llega en 2–4 días hábiles", meta: "$99" },
                                             { value: "pickup", title: "Recoger en el estudio", description: "Listo mañana en recepción", meta: "Gratis" }
                                           ]) %>

    <%= render Ui::RadioCardsComponent.new(name: "order[payment_method]", id: "radio-cards-demo-payment", label: "Método de pago",
                                           columns: 2, hint: "El link de pago llega por correo y vence en 24 horas.", class: "hidden @lg:grid") do |group| %>
      <% group.with_option(value: "card", title: "Tarjeta", description: "Visa, Mastercard o AMEX", meta: "3 MSI", icon: :credit_card) %>
      <% group.with_option(value: "stripe", title: "Link de pago", description: "Paga desde tu teléfono", icon: :link) %>
      <% group.with_option(value: "cash", title: "Efectivo en recepción", description: "Antes de tu primera clase", icon: :banknote) %>
      <% group.with_option(value: "oxxo", title: "OXXO", description: "Próximamente", disabled: true, icon: :store) %>
    <% end %>
  </div>
</div>

Qué hace

  • El marco viaja con cuatro resortes "snappy" (x, y, ancho, alto): en 2 columnas se mueve en diagonal y un cambio a medio camino sigue de donde va.
  • El círculo se llena con el resorte "responsive" y aparece el punto; el de la anterior se vacía.
  • Sin JS es un grupo de radios normal y la tarjeta elegida se marca con CSS (:has(:checked)).
  • Se reacomoda si cambia el ancho o se resetea el formulario.

Props

Nombre Tipo Default Descripción
name String nil Nombre de los radios. Con form: + attribute: sale del builder.
options [{ value:, title:, description:, meta:, icon:, disabled: }] [] Opciones (también [título, valor, descripción]). O con slots: with_option(...) { ícono }.
label String nil El <legend> del grupo (se ve como la etiqueta de Field).
selected String nil Valor elegido al cargar (con form: sale del modelo).
columns 1 | 2 | 3 | 4 1 Columnas cuando el grupo tiene ancho (container queries); angosto siempre es una.
form: + attribute: FormBuilder, Symbol nil Nombre, id, lo elegido y el error salen del modelo.
hint / error String nil Ayuda y error del grupo (el del modelo se toma solo).
required / optional / disabled Boolean false Asterisco, Opcional o el grupo entero deshabilitado (disabled por opción en options).
**attrs Hash {} id, class, data… van al <fieldset>.

Accesibilidad