Alert
v0.0.10
mix mishka.ui.gen.headless alert
Overview of the Phoenix and LiveView Headless Alert Component
The Mishka Chelekom Headless Alert is an unstyled Phoenix function component for a message the user did not ask for, such as a saved draft or a failed request. It renders one div with live region semantics and splits the message into parts: icon, title, content, actions and close. Each part has a data-part attribute and a *_class attribute, so every color, border and space comes from your own Tailwind classes.
Urgency decides how the alert is announced. The default, polite, renders role="status" with aria-live="polite", so a screen reader finishes its sentence first. assertive renders role="alert", which interrupts. off renders a plain region for a message that was already on the page at load. A title slot is linked to the root with aria-labelledby, so the heading is read before the body. With dismissible, the close button hides the alert in the browser using Phoenix LiveView JS commands, with no hook and no round trip.
Base UI Alert example - dismissible alert with a title (Phoenix headless)
Base UI Alert example - dismissible alert with a title (Phoenix headless)
<.alert
id="baseui-alert-hero"
dismissible
class="flex w-full max-w-96 items-start gap-3 rounded-md border border-neutral-200 bg-white p-3 text-sm text-neutral-950 dark:border-neutral-800 dark:bg-neutral-950 dark:text-white"
title_class="block font-medium"
content_class="flex-1"
close_class="rounded-sm text-neutral-500 hover:text-neutral-950 dark:hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-950 dark:focus-visible:outline-white"
>
<:title>Draft saved</:title>
Your changes are stored locally until you publish.
</.alert>Base UI Alert example - polite and assertive urgency (Phoenix headless)
Base UI Alert example - polite and assertive urgency (Phoenix headless)
<div class="flex w-full max-w-96 flex-col gap-2">
<.alert
id="baseui-alert-polite"
urgency="polite"
class="rounded-md border border-neutral-200 bg-white p-3 text-sm text-neutral-950 dark:border-neutral-800 dark:bg-neutral-950 dark:text-white"
>
Saved a moment ago.
</.alert>
<.alert
id="baseui-alert-assertive"
urgency="assertive"
class="rounded-md border border-red-600 bg-white p-3 text-sm text-red-700 dark:border-red-500 dark:bg-neutral-950 dark:text-red-400"
>
Could not reach the server.
</.alert>
</div>Dismissing an alert
dismissible adds a close button. It is a button with type="button" and an aria-label taken from close_label, which defaults to Dismiss. The glyph is ✕ unless you fill the close_icon slot. By default the button hides the alert with Phoenix.LiveView.JS.hide/1, aimed at the alert's own id. That is why id is required and has to be unique.
on_dismiss changes what the button does. Pass a %Phoenix.LiveView.JS{} to replace the default command, or a string to push that LiveView event instead. Use the event when the server has to forget the message, then stop rendering the alert in your template. The event is pushed without a payload.
<.alert :if={@saved?} id="draft-saved" dismissible on_dismiss="forget_saved">
<:title>Draft saved</:title>
Your changes are stored locally until you publish.
</.alert>def handle_event("forget_saved", _params, socket) do
{:noreply, assign(socket, :saved?, false)}
endIcon and actions
The icon slot renders before the message inside a span marked aria-hidden, so keep it to decoration. The actions slot renders after the message and holds buttons or links. Style them with icon_class and actions_class. The title goes in the title slot and is styled with title_class.
Parts & data attributes
The root carries data-urgency, and data-dismissible when the alert can be dismissed. The parts are marked data-part="icon", data-part="content", data-part="title", data-part="actions" and data-part="close". The title sits inside the content part, before the message. Every element also has a structural class such as chelekom-alert__content that you can target from your own CSS. Extra attributes you pass, such as data-* or aria-*, land on the root.
Accessibility
Follows the WAI-ARIA Alert pattern. Polite alerts use role="status" and assertive ones use role="alert". The title names the region through aria-labelledby, and the icon is hidden from assistive technology. The close button is a native button, so Enter and Space dismiss the alert.
Attributes
| Name | Type | Default | Values | Required | Description |
|---|---|---|---|---|---|
id
|
string
| — | — | Yes | Unique id (anchors the title and the dismiss target) |
urgency
|
string
|
polite
|
politeassertiveoff
| No | How the message is announced: status | alert | plain region |
dismissible
|
boolean
|
false
| — | No | Render a close button |
on_dismiss
|
any
| — | — | No | A JS command or LiveView event name; defaults to hiding the alert client-side |
close_label
|
string
|
Dismiss
| — | No | Accessible label for the close button |
class
|
any
| — | — | No | Extra classes for the root |
title_class
|
any
| — | — | No | — |
content_class
|
any
| — | — | No | — |
close_class
|
any
| — | — | No | — |
actions_class
|
any
| — | — | No | — |
icon_class
|
any
| — | — | No | — |
rest
|
global
| — | — | No | — |
Slots
| Name | Required | Description |
|---|---|---|
icon
| No | Leading icon (decorative — hidden from assistive tech) |
title
| No | Short heading, announced before the body |
actions
| No | Buttons or links at the end of the alert |
close_icon
| No | Custom close glyph; falls back to ✕ |
inner_block
| Yes | The message |
Options
Each option takes one or more of its values, separated by commas.
| Option | Values |
|---|---|
--type
|
alert
|
--module
| A module name of your own |
What it generates
mix mishka.ui.gen.headless alert