Alert

New

Overview

Alert boxes of various forms and colors, which can optionally be dismissed by the user.

Invitation sent to alex@example.com.
HEEx
<div class="w-full max-w-md">
  <Alert.alert>Invitation sent to alex@example.com.</Alert.alert>
</div>

Colors

Choose a semantic color. Warning and danger alerts use an assertive live region; the other colors use a polite status region.

Background sync paused.
Your team workspace is ready.
Draft review opens Friday.
12 contacts were imported.
HEEx
<div class="grid w-full max-w-md gap-3">
  <Alert.alert>Background sync paused.</Alert.alert>
  <Alert.alert color={:primary}>Your team workspace is ready.</Alert.alert>
  <Alert.alert color={:info}>Draft review opens Friday.</Alert.alert>
  <Alert.alert color={:success}>12 contacts were imported.</Alert.alert>
  <Alert.alert color={:warning}>Your API key expires in 3 days.</Alert.alert>
  <Alert.alert color={:danger}>Webhook delivery failed.</Alert.alert>
</div>

Titles

Add a title when the alert needs a short heading before its message.

Export ready

The customer activity report is ready to download.
HEEx
<div class="grid w-full max-w-md gap-3">
  <Alert.alert color={:success} title="Export ready">
    The customer activity report is ready to download.
  </Alert.alert>
  <Alert.alert color={:warning} title="Usage limit approaching">
    This workspace has used 85% of its monthly event allowance.
  </Alert.alert>
  <Alert.alert color={:danger} title="Webhook disabled">
    Repeated delivery failures paused requests to the configured endpoint.
  </Alert.alert>
</div>

Custom or hidden icon

Use the icon slot to replace the semantic icon, or hide_icon when the text already communicates the message.

Activity view enabled

Recent workspace events now appear in one timeline.

Backfill complete

Events from the previous 30 days are now available.
HEEx
<div class="grid w-full max-w-md gap-3">
  <Alert.alert color={:info} title="Activity view enabled">
    <:icon><Icon.icon name="hero-megaphone" class="size-5" aria-hidden="true" /></:icon>
    Recent workspace events now appear in one timeline.
  </Alert.alert>
  <Alert.alert color={:success} title="Backfill complete" hide_icon>
    Events from the previous 30 days are now available.
  </Alert.alert>
</div>

Persistent

Set persistent for messages that remain until a server render replaces them or the underlying condition changes.

HEEx
<div class="grid w-full max-w-md gap-3">
  <Alert.alert color={:warning} title="Read-only mode" persistent>
    You don’t have edit access to this workspace.
  </Alert.alert>
  <Alert.alert color={:danger} title="Region degraded" persistent>
    Elevated error rates are under investigation in eu-west-2.
  </Alert.alert>
</div>

Different Content

If you have any actions you want to include in the alert, you can just include them at the end of the inner_block slot.

Setup incomplete

Add Dizzy’s stylesheet to apply the component theme. Open the installation guide
HEEx
<div class="grid w-full max-w-md gap-3">
  <Alert.alert color={:warning} title="Draft has local edits">
    Publish the current draft or restore the last published version.
    <div class="mt-3 flex flex-wrap gap-2">
      <Button.button size={:xs}>Publish draft</Button.button>
      <Button.button size={:xs} kind={:ghost}>Restore version</Button.button>
    </div>
  </Alert.alert>
  <Alert.alert color={:info} title="Setup incomplete">
    Add Dizzy’s stylesheet to apply the component theme.
    <a
      href="/docs/installation"
      class="mt-3 block w-fit text-sm font-medium underline underline-offset-4 hover:no-underline"
    >
      Open the installation guide
    </a>
  </Alert.alert>
  <Alert.alert color={:danger} title="Import needs review">
    Three rows were skipped:
    <ul class="mt-2 list-inside list-disc space-y-1">
      <li>Row 18 is missing an email address.</li>
      <li>Row 31 has an invalid time zone.</li>
      <li>Row 47 duplicates an existing contact.</li>
    </ul>
  </Alert.alert>
</div>

Server-side dismissal

You may pass a Phoenix.LiveView.JS command to on_close. It runs before the built-in local hide animation. You can do this if you want to condtionally render the alert, and want to hide it for good for instance, or if you just want to trigger something to happen when you close it.

Terms updated

Review the updated terms before continuing.
HEEx
<div class="w-full max-w-md">
  <Alert.alert
    color={:info}
    title="Terms updated"
    on_close={JS.push("demo-action", value: %{action: "Alert dismissal recorded"})}
  >
    Review the updated terms before continuing.
  </Alert.alert>
</div>

Screen Banner

Use position: fixed to overlay a full-width alert at the top of the viewport.

HEEx
<div class="flex flex-wrap justify-center gap-2">
  <Button.button
    size={:sm}
    phx-click={JS.show(to: "#dismissible-screen-banner", display: "grid")}
  >
    Show dismissible banner
  </Button.button>
  <Button.button
    size={:sm}
    kind={:outline}
    phx-click={JS.show(to: "#persistent-screen-banner", display: "grid")}
  >
    Show persistent banner
  </Button.button>
</div>

<Alert.alert
  id="dismissible-screen-banner"
  color={:info}
  title="Database maintenance tonight"
  class="fixed inset-x-0 top-0 z-50 hidden w-full rounded-none! border-x-0 border-t-0 bg-blue-50! shadow-md dark:bg-blue-950!"
>
  New writes will pause for about five minutes at 02:00 UTC.
</Alert.alert>

<Alert.alert
  id="persistent-screen-banner"
  color={:warning}
  title="Incident response in progress"
  persistent
  class="fixed inset-x-0 top-0 z-50 hidden w-full rounded-none! border-x-0 border-t-0 bg-warning-surface! shadow-md"
>
  This banner remains visible until you refresh the page.
</Alert.alert>

Portal Screen Banner

This example shows how you may use Phoenix.Component.portal/1 to render an alert up at the top of the viewport, before the rest of the body tag content.

This requires you to put something at that location next to where you want it to go in the layout obviously. In the previous example, we showed off instead using position: fixed to keep the alert in the same place in the DOM, but render it up at the top of the viewport. The tradeoff is of course that then you won't "push" down the rest of the body content.

HEEx
<%!-- In your root layout, before the application content --%>
<div id="screen-banner-portal"></div>

<%!-- In your LiveView --%>
<div class="flex justify-center">
  <Button.button
    id="show-portal-screen-banner"
    size={:sm}
    phx-click={
      JS.show(to: "#portal-screen-banner", display: "grid")
      |> JS.focus(to: "#portal-screen-banner")
    }
  >
    Show portal banner
  </Button.button>
</div>

<.portal id="portal-screen-banner-source" target="#screen-banner-portal">
  <Alert.alert
    id="portal-screen-banner"
    color={:success}
    title="Deployment complete"
    tabindex="-1"
    on_close={JS.focus(to: "#show-portal-screen-banner")}
    class="hidden w-full rounded-none! border-x-0 border-t-0 bg-success-surface! shadow-md"
  >
    The latest version is now available to everyone.
  </Alert.alert>
</.portal>

Form error summary

A persistent danger alert can summarize validation errors before the related fields.

HEEx
<div class="w-full max-w-md">
  <Alert.alert color={:danger} title="Workspace setup needs attention" persistent>
    Resolve these fields before creating the workspace.
    <ul class="mt-2 list-inside list-disc space-y-1">
      <li>The workspace slug is already in use.</li>
      <li>Select a default time zone.</li>
      <li>Enter a valid billing email.</li>
    </ul>
  </Alert.alert>
</div>

Add this module

terminal
mix dizzy.add alert

Component API

Alert.alert

Attributes

Attributes for Alert.alert
NameTypeDefault Values
class :any nil—
color :atom :default:default, :primary, :info, :success, :warning, :danger
hide_icon :boolean false—
on_close :any %Phoenix.LiveView.JS{ops: []}—
persistent :boolean false—
rest :global nil—
title :string nil—

Slots

Slots for Alert.alert
NameRequired
icon Optional
inner_block Required

Explore Dizzy