Alert / banner

Use alerts for things that remain true while the page is open: "Anmeldung offen bis 31. Oktober", "3 Bewerbende ohne Gebühr", "Webling ist gerade nicht erreichbar". For short confirmations of what just happened use a toast; for field errors use the form field and error summary.

The tone sets colour and icon and is written as data-status: info (default), neutral, success, warning, danger. Look (design guide §9.4): subtle status background, a 4 px status-fill edge on the start side, status icon (20 px) and title in the status text colour, body in --color-text. The title says what is going on in one line; the body says what it means and what to do. Offer the next step as a link or one action button.

Page-level banners (offline, lock, impersonation) sit directly below the top bar, full width and without radius: add data-banner to the element (page code; render produces the in-page form). The connection banner is its own component (Offline banner).

Errors follow UX guide §7.3: a human message, what happened, what to do — never raw HTTP codes or provider messages. Show the trace id small and selectable (traceId) so support can find the case.

role="status" (default) is announced politely; use role: "alert" only for urgent errors that appear after a user action. Alerts present when the page loads are not announced either way — they are read in page order.

Examples

Info

Anmeldung offen bis 31. Oktober

Danach erstellt das System die Prüfungsgruppen automatisch.

Data
render({
  "title": "Anmeldung offen bis 31. Oktober",
  "body": "Danach erstellt das System die Prüfungsgruppen automatisch."
})
Markup
<div class="alert" role="status"><svg class="icon" aria-hidden="true"><use href="../../packages/ui/icons/icons.svg#info"/></svg><div class="alert__body">
<p class="alert__title">Anmeldung offen bis 31. Oktober</p>
<p>Danach erstellt das System die Prüfungsgruppen automatisch.</p>
</div></div>

Success

12 Gurtgrade in Webling gespeichert

Data
render({
  "tone": "success",
  "title": "12 Gurtgrade in Webling gespeichert"
})
Markup
<div class="alert" data-status="success" role="status"><svg class="icon" aria-hidden="true"><use href="../../packages/ui/icons/icons.svg#check-circle"/></svg><div class="alert__body">
<p class="alert__title">12 Gurtgrade in Webling gespeichert</p>
</div></div>

Warning with link

3 Bewerbende ohne Gebühr

Ohne Gebühr können keine Rechnungen erstellt werden. Gebühren festlegen

Data
render({
  "tone": "warning",
  "title": "3 Bewerbende ohne Gebühr",
  "body": "Ohne Gebühr können keine Rechnungen erstellt werden.",
  "link": {
    "href": "/belt-tests/2026-11/fees",
    "label": "Gebühren festlegen"
  }
})
Markup
<div class="alert" data-status="warning" role="status"><svg class="icon" aria-hidden="true"><use href="../../packages/ui/icons/icons.svg#alert-triangle"/></svg><div class="alert__body">
<p class="alert__title">3 Bewerbende ohne Gebühr</p>
<p>Ohne Gebühr können keine Rechnungen erstellt werden. <a href="/belt-tests/2026-11/fees">Gebühren festlegen</a></p>
</div></div>

Error with retry and trace id

Data
render({
  "tone": "danger",
  "role": "alert",
  "title": "Webling ist gerade nicht erreichbar",
  "body": "Deine Änderungen sind gespeichert und werden übertragen, sobald Webling wieder antwortet.",
  "action": {
    "action": "retry",
    "label": "Erneut versuchen"
  },
  "traceId": "tr-8f2a"
})
Markup
<div class="alert" data-status="danger" role="alert"><svg class="icon" aria-hidden="true"><use href="../../packages/ui/icons/icons.svg#alert-circle"/></svg><div class="alert__body">
<p class="alert__title">Webling ist gerade nicht erreichbar</p>
<p>Deine Änderungen sind gespeichert und werden übertragen, sobald Webling wieder antwortet.</p>
<p class="u-small">Fehler-ID: <code>tr-8f2a</code></p>
<div class="button-row" data-align="start"><button class="button" type="button" data-size="sm" data-action="retry">Erneut versuchen</button></div>
</div></div>

Neutral note

Dieses Training wurde aus der Vorlage «Kinder Dienstag» erstellt.

Data
render({
  "tone": "neutral",
  "title": "Dieses Training wurde aus der Vorlage «Kinder Dienstag» erstellt."
})
Markup
<div class="alert" data-status="neutral" role="status"><svg class="icon" aria-hidden="true"><use href="../../packages/ui/icons/icons.svg#info"/></svg><div class="alert__body">
<p class="alert__title">Dieses Training wurde aus der Vorlage «Kinder Dienstag» erstellt.</p>
</div></div>

Data contract

What render(data) accepts — validated against this JSON Schema in development and tests. Unknown fields are rejected. The same schema is in components.json.

FieldTypeRequiredDefaultDescription
tone"info" | "neutral" | "success" | "warning" | "danger"optional"info"Meaning; sets colour and icon.
titlestringrequired—One-line summary ("Webling ist gerade nicht erreichbar").
min 1 chars
bodystringoptional—What it means and what to do, one or two sentences.
linkobjectoptional—Optional link to the next step, appended to the body.
link.hrefstringrequired—Link target URL.
link.labelstringrequired—Link text naming the step ("Gebühren festlegen").
min 1 chars
actionobjectoptional—Optional button for an in-place action (e.g. "Erneut versuchen"); the page handles clicks via data-action.
action.actionstringrequired—Action key written to data-action ("retry").
pattern ^[a-z][a-z0-9-]*$
action.labelstringrequired—Button text, a verb ("Erneut versuchen").
min 1 chars
traceIdstringoptional—Support/trace id for errors, shown small as "Fehler-ID: …".
role"status" | "alert"optional"status"Live-region role: alert only for urgent errors after a user action.
JSON Schema
{
  "type": "object",
  "additionalProperties": false,
  "required": [
    "title"
  ],
  "properties": {
    "tone": {
      "type": "string",
      "enum": [
        "info",
        "neutral",
        "success",
        "warning",
        "danger"
      ],
      "default": "info",
      "description": "Meaning; sets colour and icon."
    },
    "title": {
      "type": "string",
      "minLength": 1,
      "description": "One-line summary (\"Webling ist gerade nicht erreichbar\")."
    },
    "body": {
      "type": "string",
      "description": "What it means and what to do, one or two sentences."
    },
    "link": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "href",
        "label"
      ],
      "description": "Optional link to the next step, appended to the body.",
      "properties": {
        "href": {
          "type": "string",
          "description": "Link target URL."
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "description": "Link text naming the step (\"Gebühren festlegen\")."
        }
      }
    },
    "action": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "action",
        "label"
      ],
      "description": "Optional button for an in-place action (e.g. \"Erneut versuchen\"); the page handles clicks via `data-action`.",
      "properties": {
        "action": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9-]*$",
          "description": "Action key written to `data-action` (\"retry\")."
        },
        "label": {
          "type": "string",
          "minLength": 1,
          "description": "Button text, a verb (\"Erneut versuchen\")."
        }
      }
    },
    "traceId": {
      "type": "string",
      "description": "Support/trace id for errors, shown small as \"Fehler-ID: …\"."
    },
    "role": {
      "type": "string",
      "enum": [
        "status",
        "alert"
      ],
      "default": "status",
      "description": "Live-region role: `alert` only for urgent errors after a user action."
    }
  }
}

Markup & states

Root: div.alert — usable without render() by writing the markup directly.

Attributes

AttributeValuesDefaultDescription
data-statusneutral | success | warning | danger(none = info)Status: background, edge, icon and title colour.
data-banner——Page-level banner below the top bar: no radius (set by page code).
rolestatus | alert—Live-region politeness.

Parts

PartDescription
.alert > svg.iconStatus icon, 20 px, in the status text colour (decorative): info · check-circle · alert-triangle · alert-circle.
.alert__bodyText column.
.alert__titleSemibold first line in the status text colour.
.alert__body > pBody text in --color-text; links inherit it.
.button-rowOptional action button.

Behaviour & events

Module: (page code)

No built-in behaviour. Handle the optional action with a delegated listener on [data-action].

Events

EventDetailDescription
click on [data-action]event.target.closest("[data-action]").dataset.actionThe action button was pressed.

Accessibility

  • Meaning is carried by the title text, not only by colour or icon.
  • role="status" for most alerts; role="alert" only for urgent errors inserted after an action.
  • The trace id is real text, selectable for copying.

Guidance

DoSay what to do next and offer it as a link or button.
DoUse a calm warning — not an error — for offline and sync delays (UX guide §7.6).
Don'tDon't stack several alerts; combine them or show the most important one.
Don'tDon't show raw error codes, JSON or provider messages.

Related: Toast · Offline banner · Error summary · Empty state