Campana de notificaciones

Un botón de campana con contador. Cuando llega algo la insignia hace pop con resorte y la campana se balancea; el panel se abre anclado a ella con escala y opacidad desde la esquina. "Marcar como leídas" apaga los puntos en cascada y la insignia se va. Las notificaciones nuevas pueden llegar por Turbo Stream.

app/views/… (la demo de arriba)

<div class="@container w-full max-w-md">
  <div class="flex items-center justify-between gap-2 rounded-2xl border border-border bg-card py-2 pl-4 pr-2">
    <div class="flex min-w-0 items-center gap-2">
      <span class="relative size-5 shrink-0 overflow-hidden rounded-full bg-foreground" aria-hidden="true"><span class="absolute -inset-px translate-x-[40%] rounded-full bg-card"></span></span>
      <span class="hidden truncate text-sm font-semibold tracking-tight @xs:inline">Luna Estudio</span>
    </div>
    <%= render Ui::NotificationBellComponent.new(id: "notification-bell-demo", on: :card, items: [
          { title: "Se liberó un lugar en Reformer 7:00", detail: "Mañana con Iván López. Resérvalo antes de que se llene.", time: "hace 2 min" },
          { title: "Tu paquete vence en 3 días", detail: "Te quedan 2 de tus 10 clases.", time: "hace 1 h" },
          { title: "Ana García confirmó tu clase privada", detail: "Jueves 18:00 · Sala 2", time: "ayer", unread: false }
        ]) do %>
      <%= render Ui::ButtonComponent.new(variant: :ghost, size: :sm, data: {
            action: "notification-bell#add",
            notification_bell_title_param: "Nueva clase: Yin al atardecer",
            notification_bell_detail_param: "Viernes 19:30 con Sofía Ruiz. Quedan 8 lugares.",
            notification_bell_time_param: "Ahora"
          }) do %>Simular aviso<% end %>
    <% end %>
  </div>
</div>

Qué hace

  • El panel es un popover nativo en la capa superior, anclado con JS; si abajo no cabe abre hacia arriba.
  • Turbo Stream: turbo_stream.prepend "eui-notifications-list", Ui::NotificationBellComponent::Notification.new(title: …).
  • Acción notification-bell#add con params title, detail y time (la demo la usa).
  • Eventos notification-bell:open y notification-bell:read ({ count }).

Props

Nombre Tipo Default Descripción
items Array<Hash> [] Notificaciones: title, detail, time (String o Time), unread, href.
with_notification slot — La misma notificación por slot (title:, detail:, time:, unread:, href:).
read_url String nil Marcar como leídas envía un PATCH aquí (button_to, Turbo).
id String "eui-notifications" Prefijo de ids; la lista es <id>-list (destino de Turbo Streams).
label String "Notificaciones" Nombre del botón y título del panel.
align :end | :start :end Borde de la campana al que se alinea el panel.
on :background | :card | :raised :background Superficie detrás: color del anillo de la insignia.

Accesibilidad