Skip to content

Alert

Alert
Thymeleaf source
<sl:alert>
<sl:icon name="circle-check"/>
<sl:alert-title>Order placed</sl:alert-title>
<sl:alert-description>We will email you when it ships.</sl:alert-description>
</sl:alert>
Rendered HTML
<div class="alert">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<circle cx="12" cy="12" r="10"></circle>
<path d="m16 9-5.5 5.5L8 12"></path>
</svg>
<div class="alert-title">Order placed</div>
<div class="alert-description">We will email you when it ships.</div>
</div>

<sl:alert> holds an optional <sl:icon>, then <sl:alert-title> and <sl:alert-description>, as in shadcn/ui. The icon takes the alert’s colour and sits beside both. Use either part on its own.

Title only, no icon
Thymeleaf source
<sl:alert>
<sl:alert-title>Your trial ends in 3 days.</sl:alert-title>
</sl:alert>
Rendered HTML
<div class="alert">
<div class="alert-title">Your trial ends in 3 days.</div>
</div>
Destructive
Thymeleaf source
<sl:alert variant="destructive">
<sl:icon name="circle-alert"/>
<sl:alert-title>Payment failed</sl:alert-title>
<sl:alert-description>
<p>Your card was declined. Check the details and try again:</p>
<ul>
<li>the expiry date</li>
<li>the billing address</li>
</ul>
</sl:alert-description>
</sl:alert>
Rendered HTML
<div class="alert" data-variant="destructive">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" x2="12" y1="8" y2="12"></line>
<line x1="12" x2="12.01" y1="16" y2="16"></line>
</svg>
<div class="alert-title">Payment failed</div>
<div class="alert-description">
<p>Your card was declined. Check the details and try again:</p>
<ul>
<li>the expiry date</li>
<li>the billing address</li>
</ul>
</div>
</div>

An alert is not announced by itself. Most alerts are part of the page when it loads, and a screen reader reads them in order with everything else; announcing them too would interrupt the user for no reason.

When an alert appears later, for example in the response to an htmx request, add role="alert". A screen reader then reads it as soon as it is inserted. Like any other attribute, role passes through to the rendered element. An alert that takes the focus when it appears (tabindex="-1" and autofocus, which htmx honours in swapped content) is read out because of the focus, and needs no role; see Forms with htmx.

Announcedrole="alert" makes a screen reader read the alert as soon as it appears.
Thymeleaf source
<sl:alert variant="destructive" role="alert">
<sl:icon name="circle-alert"/>
<sl:alert-title>The order could not be saved</sl:alert-title>
<sl:alert-description>Someone else changed it. Reload the page to see their changes.</sl:alert-description>
</sl:alert>
Rendered HTML
<div class="alert" data-variant="destructive" role="alert">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" x2="12" y1="8" y2="12"></line>
<line x1="12" x2="12.01" y1="16" y2="16"></line>
</svg>
<div class="alert-title">The order could not be saved</div>
<div class="alert-description">Someone else changed it. Reload the page to see their changes.</div>
</div>

For a message that is not urgent, role="status" is announced when the user is idle instead of at once.

AttributeValuesDefaultDescription
variantdefault destructivedefaultVisual style of the alert.

Every prop can also be set from an expression: th:variant="${...}". Any other attribute passes through to the rendered element, and class is appended.

AttributeValuesDefaultDescription
level1 2 3 4 5 6—Heading level. With it the title is a heading (role="heading" and aria-level) that screen reader users can jump to; without it, plain text, as in shadcn/ui.

Every prop can also be set from an expression: th:level="${...}". Any other attribute passes through to the rendered element, and class is appended.

sl:alert-description declares no props; every attribute passes through.