Admin
Estado: BetaActividad reciente
"Pedidos recientes" del panel con el lenguaje del sistema: iniciales, título, cuándo pasó, monto alineado y la pastilla de estado. Lo que llega por Turbo Stream entra subiendo, se ilumina un momento y se anuncia a lectores de pantalla. Recibe ítems genéricos (hashes).
- Admin
- Turbo Stream
- aria-live
Pedidos recientes
En vivo- #36 · Mariana Peña$1,300Completado
- #35 · Diego Hernández$2,079Completado
- #34 · invitada@correo.mx$340Completado
- #33 · Lucía Torres$890.50Cancelado
Sin actividad todavía
Pedidos recientes
En vivo- #36 · Mariana Peña$1,300Completado
- #35 · Diego Hernández$2,079Completado
- #34 · invitada@correo.mx$340Completado
- #33 · Lucía Torres$890.50Cancelado
Sin actividad todavía
app/views/… (la demo de arriba)
<%# Cada fila es un hash: quién, referencia, hora, monto y estado. En tu app un
adaptador arma esos hashes desde tus modelos, sin consultas en la vista. %>
<% now = Time.current %>
<% pedido = ->(id, title, ago, amount, status = "completed") do
{ id: "activity_order_#{id}", reference: "##{id}", title:, time: now - ago, amount:, status:,
status_label: { "completed" => "Completado", "cancelled" => "Cancelado" }[status], href: "#pedido-#{id}" }
end %>
<% pedidos = [
pedido.(36, "Mariana Peña", 3.hours, 1300),
pedido.(35, "Diego Hernández", 5.hours, 2079),
pedido.(34, "invitada@correo.mx", 1.day, 340),
pedido.(33, "Lucía Torres", 2.days, 890.5, "cancelled")
] %>
<% nuevo = pedido.(37, "Sofía Ruiz", 0.seconds, 1650) %>
<div class="flex w-full max-w-md flex-col items-center gap-4" data-controller="nested-form">
<%= render Ui::ActivityFeedComponent.new(items: pedidos, title: "Pedidos recientes", href: "#pedidos", id: "activity-feed-demo",
live: true, limit: 5, class: "w-full") %>
<%# En la app el servidor manda este turbo_stream.prepend (p. ej. al completarse el pago);
aquí el botón lo inyecta para ver cómo entra la fila. Con el mismo id, Turbo
reemplaza la fila en vez de duplicarla. %>
<template data-nested-form-target="template">
<turbo-stream action="prepend" target="activity-feed-demo-list">
<template><%= render Ui::ActivityFeedComponent::ItemComponent.new(**nuevo) %></template>
</turbo-stream>
</template>
<div data-nested-form-target="items" hidden></div>
<%= render Ui::ButtonComponent.new(variant: :secondary, size: :sm, data: { action: "nested-form#add" }) do %>Simular pedido nuevo<% end %>
</div>Qué hace
- La lista tiene id «<id>-list»: el destino de turbo_stream.prepend.
- Las filas nuevas entran con animate-rise y un destello breve; las que ya estaban no se mueven.
- Montos como $1,350 (centavos solo si los hay) con cifras tabulares.
- Fechas relativas en español («hace 3 horas», «ayer») con la fecha completa al pasar.
Props
| Nombre | Tipo | Default | Descripción |
|---|---|---|---|
| title / href / href_label | String | — / nil / "Ver todos" | Encabezado y el enlace a la lista completa. |
| items | Array<Hash> | [] | Ítems genéricos: title, reference, initials, time, meta, amount, status, status_label, href, id. También con el slot with_item(…). |
| ItemComponent.new(**item) | componente | — | La fila suelta desde un ítem, para el turbo_stream.prepend a «<id>-list». |
| limit | Integer | nil | Máximo de filas; al llegar una nueva sale la más vieja. |
| live | Boolean | false | Pastilla «En vivo» junto al título (cuando la vista escucha un stream). |
| empty_title / empty_description | String | "Sin actividad todavía" | El estado vacío; se va solo cuando llega la primera fila. |
Accesibilidad
- Es una <section> con nombre y una lista ordenada de verdad.
- Cada fila nueva se anuncia por aria-live («Nuevo #37 · Sofía Ruiz, $1,650»).
- El estado siempre va con texto; las iniciales son decorativas.