AuroraUI.Components.Feedback (Aurora UI v0.1.1)

View Source

Feedback family — alert, toast (with region), inline status, connection state.

These components tell the user what just happened, what is happening, and whether the app can still reach the server. Getting them right is mostly an exercise in restraint: the wrong live-region strategy turns a helpful app into a screen-reader that will not stop talking.

Live-region strategy (read before adding announcements)

There are three distinct "loudness" levels here and each maps to a specific ARIA construct:

  • alert/1 is static. It is server-rendered once, in place, as part of the page. info/success/warning/neutral carry role="status" (a polite live region); danger — or any alert with assertive — carries role="alert" (assertive). Because the node is present at render time it is announced once and never re-announced. It is not a live-region that we push updates into, so it cannot spam. Use it for validation summaries, empty states, and inline warnings.

  • toast_group/1 is the one streaming live region on the page. It owns a single aria-live politeness setting (polite by default, assertive only when a group is dedicated to errors). Individual toast/1 items are appended into it as list items; the region — not each toast — is what AT observes, so N toasts appearing in one patch are announced as they land rather than as N competing regions. To avoid spam the AuroraToast hook is responsible for: pause-on-hover / pause-on-focus (timers freeze while the pointer or keyboard focus is inside the region), de-duplication (a toast whose data-aui-dedup-key matches a visible one refreshes that toast instead of stacking a copy), and honoring prefers-reduced-motion. Toasts are ephemeral: never put an error the user must act on only in a toast. A critical, persistent error belongs in an alert/1 (or a toast with timeout={0}, which the hook leaves on screen until dismissed).

  • inline_status/1 and connection_state/1 are ambient. inline_status/1 is a plain labelled indicator (dot + text) with no live region — poll/refresh changes it silently. connection_state/1 is a single polite region that the AuroraConnectionState hook drives from the LiveView socket, reflecting connected / connecting / disconnected onto data-aui-conn. It is deliberately calm: it shows a "reconnecting…" affordance, never steals focus, and never discards the user's in-progress work — it only reports reachability.

Semantics

All dismiss controls are real <button>s with an accessible name and the shared .aui-focusable ring; decorative icons are aria-hidden. Nothing here relies on color alone — severity is always carried by text and/or an icon in addition to the token color.

Summary

Functions

A static, inline alert. Rendered once as part of the page — not a channel we push updates into, so it announces itself a single time and cannot spam.

A LiveView connection indicator wired to the AuroraConnectionState hook. The hook reflects the socket state onto data-aui-conn (connected / connecting / disconnected) and cooperates with Phoenix's own .phx-loading / .phx-error body classes; CSS then reveals the matching label.

A compact status indicator: a colored dot plus a text label, e.g. "Operational" or "Degraded". No live region — refresh it however you like; it changes silently. The dot is decorative and the label always carries the meaning, so it is legible without color.

One toast: a single list item inside a toast_group/1. Severity, optional title, body, an optional action, and a dismiss button. data-aui-timeout hands the auto-dismiss delay to the AuroraToast hook; timeout={0} omits it so the toast persists — the right choice for a critical error you cannot lose.

The single streaming live region that hosts toast/1 items. Renders the data-aui-toast-region container wired to the AuroraToast hook, which owns the timers, pause-on-hover/focus, and de-duplication.

Functions

alert(assigns)

A static, inline alert. Rendered once as part of the page — not a channel we push updates into, so it announces itself a single time and cannot spam.

info/success/warning/neutral use role="status" (polite); danger (or any alert with assertive) uses role="alert" (assertive).

When not to use

For transient confirmations that should auto-dismiss, reach for toast/1. For a per-field validation message, use the field/form components instead.

Examples

<.alert variant="success" title="Saved">Your changes are live.</.alert>

<.alert variant="danger" on_dismiss={JS.hide(to: "#quota")} id="quota">
  You have hit your plan's quota.
</.alert>

Attributes

  • variant (:string) - Severity of the message. Drives icon color and default ARIA role. Defaults to "info". Must be one of "info", "success", "warning", "danger", or "neutral".
  • title (:string) - Optional short heading rendered above the body. Defaults to nil.
  • assertive (:boolean) - Force role=alert (assertive live region). danger is assertive automatically. Defaults to false.
  • on_dismiss (:any) - phx-click event name or JS command; when set, a dismiss button is shown. Defaults to nil.
  • dismiss_label (:string) - Defaults to "Dismiss".
  • Global attributes are accepted.

Slots

  • icon - leading status icon; decorative (aria-hidden).
  • inner_block (required) - the message body.

connection_state(assigns)

A LiveView connection indicator wired to the AuroraConnectionState hook. The hook reflects the socket state onto data-aui-conn (connected / connecting / disconnected) and cooperates with Phoenix's own .phx-loading / .phx-error body classes; CSS then reveals the matching label.

It is intentionally calm: a single polite live region (so a reconnect is announced once, not spammed), a visible "reconnecting…" affordance, and no focus-stealing. It reports reachability only — it never discards in-progress work.

Examples

<.connection_state id="conn" />

Attributes

  • id (:string) - Stable id for the hook target. Defaults to nil.
  • connected_label (:string) - Defaults to "Connected".
  • connecting_label (:string) - Defaults to "Reconnecting…".
  • disconnected_label (:string) - Defaults to "Offline".
  • hide_when_connected (:boolean) - Collapse the indicator while healthy; reveal only on trouble. Defaults to true.
  • Global attributes are accepted.

inline_status(assigns)

A compact status indicator: a colored dot plus a text label, e.g. "Operational" or "Degraded". No live region — refresh it however you like; it changes silently. The dot is decorative and the label always carries the meaning, so it is legible without color.

Examples

<.inline_status severity="success" label="Operational" />
<.inline_status severity="warning" pulse>Degraded</.inline_status>

Attributes

  • severity (:string) - Maps to the dot color; the label still carries the meaning in text. Defaults to "neutral". Must be one of "info", "success", "warning", "danger", or "neutral".
  • label (:string) - status text; alternatively pass an inner block. Defaults to nil.
  • pulse (:boolean) - Animate the dot to hint a live/degraded state (respects reduced-motion). Defaults to false.
  • Global attributes are accepted.

Slots

  • inner_block - status text (overrides label).

toast(assigns)

One toast: a single list item inside a toast_group/1. Severity, optional title, body, an optional action, and a dismiss button. data-aui-timeout hands the auto-dismiss delay to the AuroraToast hook; timeout={0} omits it so the toast persists — the right choice for a critical error you cannot lose.

Examples

<.toast id="t1" severity="success" title="Copied">Link copied to clipboard.</.toast>

<.toast id="t2" severity="danger" title="Upload failed" timeout={0}>
  <:action><.button size="sm" phx-click="retry">Retry</.button></:action>
  We could not reach the server.
</.toast>

Attributes

  • id (:string) - Defaults to nil.
  • severity (:string) - Defaults to "info". Must be one of "info", "success", "warning", "danger", or "neutral".
  • title (:string) - Defaults to nil.
  • timeout (:integer) - Auto-dismiss delay in ms. 0 keeps the toast until dismissed (persistent). Defaults to 6000.
  • dedup_key (:string) - Toasts sharing a key refresh the visible one instead of stacking a duplicate. Defaults to nil.
  • on_dismiss (:any) - phx-click event/JS run when the toast is dismissed. Defaults to nil.
  • dismiss_label (:string) - Defaults to "Dismiss".
  • Global attributes are accepted.

Slots

  • icon - leading severity icon; decorative.
  • action - one optional action control (e.g. Undo).
  • inner_block (required) - the toast body.

toast_group(assigns)

The single streaming live region that hosts toast/1 items. Renders the data-aui-toast-region container wired to the AuroraToast hook, which owns the timers, pause-on-hover/focus, and de-duplication.

Put exactly one polite toast_group/1 in your layout. Only add a second, assertive group if you have errors that must interrupt — and prefer a persistent alert/1 for anything the user must act on.

Examples

<.toast_group id="toasts">
  <.toast :for={{id, t} <- @streams.toasts} id={id} severity={t.severity} title={t.title}>
    {t.body}
  </.toast>
</.toast_group>

Attributes

  • id (:string) - Stable id for the region and its hook target. Defaults to nil.
  • label (:string) - accessible name for the region. Defaults to "Notifications".
  • assertive (:boolean) - Use an assertive live region. Reserve for a group dedicated to errors. Defaults to false.
  • Global attributes are accepted. Supports all globals plus: ["phx-update"].

Slots

  • inner_block (required) - the streamed toast/1 items.