Alert
An inline message that interrupts the reading flow to report the outcome or state of something.
When to Use
Variants
Severity
Four severities, each with an automatic icon. Pass icon only when you need to override that default.
<?= ws_alert('Your changes have been saved.', ['variant' => 'success']) ?>
<?= ws_alert('Please review the form', ['variant' => 'warning']) ?>
<?= ws_alert('An error occurred', ['variant' => 'error']) ?>With a title
Add a title when the message needs more than one sentence. Keep the title to a noun phrase and let the body carry the instruction.
<?= ws_alert('Message here', [
'variant' => 'warning',
'title' => 'Session Expiring',
]) ?>Filled
Solid background instead of a tint. Reserve it for the one alert on a page that must win attention — several filled alerts together cancel each other out.
<?= ws_alert('Message', ['variant' => 'success', 'filled' => true]) ?>Without the border accent
The left border is on by default. Drop it when the alert sits inside an already-bordered container and the double edge reads as noise.
<?= ws_alert('Message', ['bordered' => false]) ?>States
Dismissible
Adds a close button that removes the alert from the DOM. Use it for messages the reader can finish with — never for an error they still need to act on.
<?= ws_alert('Message', ['dismissible' => true]) ?>With actions
Actions render as links when given href, and as buttons otherwise. Keep to two — a third is a sign the alert should be a modal.
<?= ws_alert('Message', [
'variant' => 'info',
'actions' => [
['text' => 'Action', 'href' => '/url'],
['text' => 'Another', 'onclick' => 'doSomething()'],
],
]) ?>| State | Behavior |
|---|---|
| Default | Tinted background, severity-coloured left border, auto icon. |
| Dismissed | The close button runs this.parentElement.remove(), deleting the whole alert. There is no animation and no event — if you need to know it was dismissed, add your own handler via attrs. |
| Hover (actions) | Action links and buttons carry a --transition-fast colour shift; the alert body itself has no hover state. |
Real-World Usage
A form-level validation summary — error severity, a title naming the problem, the body listing what to fix, and no dismiss button because the reader still has work to do.
<?php if ($errors): ?>
<?= ws_alert(implode(' ', $errors), [
'variant' => 'error',
'title' => "This workshop can't be saved yet",
]) ?>
<?php endif; ?>Options
The message is the first positional argument; everything else goes in the options array.
| Option | Type | Default | Purpose |
|---|---|---|---|
$message | string | '' | Body text. Positional. Rendered as raw HTML — see the security note below. |
variant | string | 'info' | info | success | warning | error |
title | string | null | Optional heading above the message. Escaped. |
icon | string | by variant | Overrides the automatic icon: check_circle (success), warning, error, info. |
dismissible | bool | false | Adds the close button and the .ws-alert--dismissible class. |
bordered | bool | true | Left border accent. On by default — pass false to remove. |
filled | bool | false | Solid background instead of a tint. |
actions | array | [] | [['text' => …, 'href' => …]] renders links; omit href and pass onclick for buttons. |
id | string | null | Element ID |
class | string | '' | Additional CSS classes |
attrs | array | [] | Extra HTML attributes as key/value pairs |
$message is echoed unescaped so it can carry inline markup, while title and action text are escaped. Never pass unsanitised user input as the message — escape it at the call site with htmlspecialchars().
Accessibility
| Concern | Behavior |
|---|---|
| ARIA | The container always carries role="alert" — an assertive live region. Content injected after page load is announced immediately, interrupting whatever the screen reader was saying. |
| Keyboard | The alert itself isn't focusable. The close button and any action buttons/links are standard focusable controls reachable with Tab and activated with Enter or Space. |
| Focus | Dismissing removes the alert while focus is still on its close button, dropping focus to <body>. Move focus somewhere sensible yourself if the alert was part of a keyboard flow. |
| Labelling | The close button is labelled aria-label="Dismiss". The severity is conveyed by colour and icon only — put the severity in the words too, so it survives without either. |
| Contrast | Tinted variants pair a --color-*-light background with a --color-*-dark foreground; filled variants use --text-inverse. Don't override one side alone. |
role="alert" is applied unconditionally, including to informational alerts rendered with the page. For non-urgent messages a polite region would be the better fit; today you'd override it with attrs => ['role' => 'status'], which appends a second role attribute rather than replacing it — so the assertive one still wins.
Tokens
| Token | Used for |
|---|---|
--color-info-light / --color-info-dark | Info background and foreground |
--color-success-light / --color-success-dark / --color-success-darker | Success tint, text, and border accent |
--color-warning-light / --color-warning-dark / --color-warning-darker | Warning tint, text, and border accent |
--color-error-light / --color-error-dark | Error tint and foreground |
--text-inverse | Foreground on filled variants |
--radius-md / --radius-xl | Container and action-button corners |
--text-h3 / --text-h4 / --text-small / --text-meta | Title and message type scale |
--font-body / --font-semibold | Body face and title weight |
--transition-fast | Action and close-button hover |
CSS Classes
| Class | Purpose |
|---|---|
.ws-alert | Base container |
.ws-alert--info / --success / --warning / --error | Severity modifiers |
.ws-alert--bordered | Left border accent (applied by default) |
.ws-alert--filled | Solid background |
.ws-alert--dismissible | Reserves space for the close button |
.ws-alert__icon | Leading severity icon |
.ws-alert__content | Title + message + actions column |
.ws-alert__title | Optional heading |
.ws-alert__message | Body text |
.ws-alert__actions | Action row |
.ws-alert__action | Individual action link or button |
.ws-alert__close | Dismiss button |
Files
| File | Purpose |
|---|---|
includes/components/helpers.php | ws_alert() helper function |
includes/components/alert.php | Template — variant icon mapping and markup |
includes/components/components.css | Styles (.ws-alert rules) |