Kern GitHub

Alert

In-flow message box with severity indicator. Alpine is only needed when `dismissible="true"`.
Requires Alpine.js
Alert colors are status indicators, not actions: `info` reuses `primary`, `success` uses the shipped `success` token, and `error` reuses `destructive`. The left border is the severity indicator; the surrounding `border-border` remains the layout container. There is no warning variant because Kern has no warning token. Success stays included because `--color-success` ships in `kern.css` and is already consumed elsewhere; remove the variant if the design ruling changes. Static, in-flow alerts have no ARIA role by default. For content injected or revealed dynamically, add `role="alert"` to the root in your copied source so assistive tech treats it as an assertive live region. Dismissible alerts use Alpine (`x-data`, `x-show`) only when `dismissible="true"`.

Severities

Info:
Heads up
The default info alert is for neutral guidance.
Success:
Saved
Your changes have been saved.
Error:
Could not save
Fix the highlighted fields and try again.
1{{ partial:components/primitives/alert title="Heads up" }}
2 The default info alert is for neutral guidance.
3{{ /partial:components/primitives/alert }}
4{{ partial:components/primitives/alert title="Saved" severity="success" }}
5 Your changes have been saved.
6{{ /partial:components/primitives/alert }}
7{{ partial:components/primitives/alert title="Could not save" severity="error" }}
8 Fix the highlighted fields and try again.
9{{ /partial:components/primitives/alert }}

Body only

Info:
Alert
Short guidance can omit the title line.
1{{ partial:components/primitives/alert severity="info" }}
2 Short guidance can omit the title line.
3{{ /partial:components/primitives/alert }}

Dismissible

Success:
Draft restored
This message can be dismissed with the close button.
1{{ partial:components/primitives/alert title="Draft restored" severity="success" dismissible="true" }}
2 This message can be dismissed with the close button.
3{{ /partial:components/primitives/alert }}

Props

Name Type Default Description
severity string info Visual severity: info|success|error
title string Optional bold heading line
dismissible boolean Adds an Alpine-powered dismiss button when true
class string Additional classes merged via tw_merge (root element only)

Slots

Name Fallback / Default Description
default Alert body content

Source

1{{#
2 @name Alert
3 @desc In-flow message box with severity indicator. Alpine is only needed when `dismissible="true"`.
4 @param severity string [info] - Visual severity: info|success|error
5 @param title string - Optional bold heading line
6 @param dismissible boolean [false] - Adds an Alpine-powered dismiss button when true
7 @param class string - Additional classes merged via tw_merge (root element only)
8 @slot default - Alert body content
9#}}
10{{# format-ignore-start #}}
11{{ _severity_key = severity ?? 'info' }}
12
13{{ _borders = [
14 'info' => 'border-l-primary',
15 'success' => 'border-l-success',
16 'error' => 'border-l-destructive',
17] }}
18
19{{ _icons = [
20 'info' => 'info',
21 'success' => 'check',
22 'error' => 'error',
23] }}
24
25{{ _icon_classes = [
26 'info' => 'text-primary',
27 'success' => 'text-success',
28 'error' => 'text-destructive',
29] }}
30
31{{ _prefixes = [
32 'info' => 'Info:',
33 'success' => 'Success:',
34 'error' => 'Error:',
35] }}
36
37{{ _class_border = _borders[_severity_key] ?? _borders['info'] }}
38{{ _icon = _icons[_severity_key] ?? _icons['info'] }}
39{{ _class_icon = _icon_classes[_severity_key] ?? _icon_classes['info'] }}
40{{ _prefix = _prefixes[_severity_key] ?? _prefixes['info'] }}
41{{# format-ignore-end #}}
42<div
43 class="{{ 'border-border bg-background text-foreground relative border border-l-4 p-4 {_class_border} {class}' | tw_merge }}"
44 {{ if dismissible == 'true' }}
45 x-data="{ visible: true }"
46 x-show="visible"
47 {{ /if }}
48>
49 <div class="flex gap-3">
50 {{ svg src="icons/{_icon}" class="size-5 shrink-0 {_class_icon}" aria-hidden="true" }}
51 <div class="min-w-0 flex-1 text-sm">
52 <span class="sr-only">{{ _prefix }}</span>
53 {{ if title }}
54 <div class="font-bold">{{ title }}</div>
55 {{ /if }}
56 <div class="{{ title ?= 'mt-1' }}">
57 {{ slot }}
58 </div>
59 </div>
60 {{ if dismissible == 'true' }}
61 <button
62 type="button"
63 class="text-muted-foreground focus-visible:border-focus-text focus-visible:outline-focus active:border-focus active:bg-focus active:text-focus-text -m-1 inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-full border-2 border-transparent transition-colors hover:border-current focus-visible:outline focus-visible:outline-4"
64 aria-label="Dismiss"
65 @click="visible = false"
66 >
67 {{ svg src="icons/close" class="size-4" aria-hidden="true" }}
68 </button>
69 {{ /if }}
70 </div>
71</div>

Dependencies

Packages

1composer require marcorieser/tailwind-merge-statamic
2npm install alpinejs