Component Contract
Toast
Lightweight, non-blocking notification used to surface brief, time-sensitive messages across the CAAT Pension Plan member experience.
Live Demo
Basic Toast
Rendered
Colour Variants
Rendered
Toast with Action
Rendered
States
Interactive states on the dismiss control and the action link. Shown statically via is-* classes that mirror the live :hover / :focus-visible rules.
Stacked Toasts (positioned)
Rendered — click the button to show stacked toasts in the bottom-right corner.
Code sample
HTML
<!-- Basic toast -->
<div class="caat-toast toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="caat-toast__header toast-header">
<i class="bi bi-bell caat-toast__icon" aria-hidden="true"></i>
<span class="caat-toast__title">Notification</span>
<small class="caat-toast__meta">Just now</small>
<button type="button" class="caat-toast__close"
data-bs-dismiss="toast" aria-label="Close">
<i class="bi bi-x" aria-hidden="true"></i>
</button>
</div>
<div class="caat-toast__body">
Your contribution statement is now available.
</div>
</div>
<!-- Colour variant -->
<div class="caat-toast caat-toast--success toast" role="alert" ...>
...
</div>
<!-- Toast with action -->
<div class="caat-toast__body">
Item removed.
<a href="#" class="caat-toast__action">Undo</a>
</div>
<!-- Stacked container -->
<div class="caat-toast-container" aria-live="polite">
<!-- Multiple .caat-toast elements -->
</div>
1. Summary
| Component name | caat/components/toast |
| Purpose | Lightweight, non-blocking notification that appears briefly to confirm an action, surface a status change, or alert the member to a time-sensitive event. Used across the member portal for form confirmations, session warnings, and system messages. |
| Status | New |
| Variants | Default (blue), Success (green), Warning (amber), Error (red), Info (blue) |
| Options | Auto-dismiss toggle, dismiss delay, optional action link, optional icon |
| AEM resource type | caat/components/toast |
| AEM category | CAAT Components – Feedback |
2. Design Tokens
Toasts consume these semantic tokens — no component-specific tokens are defined.
| Token | Role |
|---|---|
--caat-color-bg-page | Toast background |
--caat-color-text | Toast body text |
--caat-color-text-muted | Meta / timestamp text |
--caat-color-border | Toast border |
--caat-blue-700 | Default / info left-border accent |
--caat-green | Success accent |
--caat-warning-accent | Warning accent |
--caat-danger-accent | Error accent |
--caat-shadow-sm | Elevation shadow |
--caat-radius | Corner radius |
--caat-font-primary | Font family |
3. Authoring Fields
| Field | Type | Required | Notes |
|---|---|---|---|
| Title | Text field | Yes | Short header text. Max 60 characters. E.g., "Success", "Session Expiring". |
| Body | Text area | Yes | Notification message. Max 200 characters. Keep concise and actionable. |
| Variant | Dropdown (default | success | warning | error | info) | Yes | Determines accent colour and header background. |
| Icon | Icon picker | No | Bootstrap Icon shown in the header (e.g., bi-check-circle-fill). |
| Action Label | Text field | No | Text for an optional action link in the body (e.g., "Undo", "View"). |
| Action URL | Path picker | No | Destination for the action link. Required if Action Label is provided. |
| Auto-dismiss | Toggle (boolean) | No | Default: on. When enabled, toast auto-hides after the configured delay. |
| Dismiss Delay | Number (ms) | No | Default: 5000. Time in milliseconds before auto-dismiss. Minimum 3000. |
4. Validation Rules
- Title and Body are mandatory; toast will not render without both.
- Title max length: 60 characters.
- Body max length: 200 characters.
- Variant is required; defaults to "default" if not set.
- If Action Label is provided, Action URL is also required (and vice-versa).
- Dismiss Delay must be ≥ 3000 ms. Values below 3000 are clamped to 3000.
- Error-variant toasts should default to
autohide: falseso members don't miss critical messages.
5. Content Guidance
| Guideline | Detail |
|---|---|
| Tone | Brief, member-friendly. Use plain language. Lead with the outcome ("Profile updated") not the action ("We have updated your profile"). |
| Use Success for | Confirmations — "Profile updated", "Beneficiary added", "Document uploaded". |
| Use Warning for | Non-critical alerts — "Session expiring in 5 min", "Incomplete form saved as draft". |
| Use Error for | Failures — "Unable to save changes", "Connection lost". Always provide guidance or retry option. |
| Use Info for | Neutral updates — "New statement available", "Scheduled maintenance tonight". |
| Action links | Use sparingly. One action per toast maximum. Label should be a verb — "Undo", "View", "Retry". |
| Don't | Use toasts for critical, blocking errors (use a modal instead). Don't stack more than 3 toasts at once. Don't use toasts for marketing or promotional content. |
6. Semantic HTML
HTL / Markup contract
<!-- Single toast -->
<div class="caat-toast caat-toast--{variant} toast"
role="alert" aria-live="assertive" aria-atomic="true"
data-bs-autohide="{autohide}" data-bs-delay="{delay}">
<div class="caat-toast__header toast-header">
<i class="bi bi-{icon} caat-toast__icon" aria-hidden="true"></i>
<span class="caat-toast__title">{title}</span>
<small class="caat-toast__meta">{timestamp}</small>
<button type="button" class="caat-toast__close"
data-bs-dismiss="toast" aria-label="Close">
<i class="bi bi-x" aria-hidden="true"></i>
</button>
</div>
<div class="caat-toast__body">
{body}
<a href="{actionUrl}" class="caat-toast__action">{actionLabel}</a>
</div>
</div>
<!-- Stacked toast container -->
<div class="caat-toast-container" aria-live="polite">
<!-- Individual .caat-toast elements injected here -->
</div>
Key decisions
role="alert"witharia-live="assertive"ensures screen readers announce the toast immediately.aria-atomic="true"ensures the entire toast content is announced as a single unit.- Close button uses
aria-label="Close"for screen-reader accessibility. - Bootstrap's
.toastclass provides the show/hide JS behaviour; BEM classes layer CAAT styling on top. - The stacked container uses
aria-live="polite"so new toasts don't interrupt the current announcement.
7. CSS Contract
| Selector | Purpose |
|---|---|
.caat-toast | Base toast — font-family, border-radius, box-shadow, left-border accent, slide-in animation. |
.caat-toast__header | Header bar — flex layout, background, bottom border, font-weight 600. |
.caat-toast__icon | Leading icon in the header. |
.caat-toast__title | Header title text — flex: 1 to fill available space. |
.caat-toast__meta | Timestamp or supplementary text in header. |
.caat-toast__close | Close button — transparent background, focus ring via --caat-focus. |
.caat-toast__body | Body content area — padding, font-size 0.875rem. |
.caat-toast__action | Action link inside body — underlined, blue-700 colour. |
.caat-toast--success | Success variant — green left border, green-tinted header. |
.caat-toast--warning | Warning variant — amber left border, amber-tinted header. |
.caat-toast--error | Error variant — red left border, red-tinted header. |
.caat-toast--info | Info variant — blue left border, blue-tinted header. |
.caat-toast-container | Fixed bottom-right container for stacked toasts. z-index: 1090. |
Sample CSS
.caat-toast {
font-family: var(--caat-font-primary, 'Libre Franklin', sans-serif);
border-radius: var(--caat-radius, 0.375rem);
border-left: 4px solid var(--caat-blue-700, #004a99);
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.15);
background-color: #fff;
color: var(--caat-ink, #212529);
animation: caat-toast-slide-in 0.3s ease-out;
}
.caat-toast--success { border-left-color: var(--caat-green, #198754); }
.caat-toast--warning { border-left-color: #ffc107; }
.caat-toast--error { border-left-color: #dc3545; }
.caat-toast--info { border-left-color: var(--caat-blue-700, #004a99); }
.caat-toast__close:focus-visible {
outline: 2px solid var(--caat-focus, #005fcc);
outline-offset: 2px;
}
.caat-toast-container {
position: fixed;
bottom: 1.5rem;
right: 1.5rem;
z-index: 1090;
display: flex;
flex-direction: column;
gap: 0.75rem;
max-width: 350px;
}
@keyframes caat-toast-slide-in {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
8. Accessibility
| Requirement | Implementation |
|---|---|
| ARIA live region | Each toast uses role="alert" and aria-live="assertive" so screen readers announce it immediately upon display. |
| Atomic announcement | aria-atomic="true" ensures the entire toast (title + body) is read as one unit. |
| Close button | Uses aria-label="Close". Receives visible focus ring (:focus-visible) via --caat-focus token. |
| Keyboard | Close button is reachable via Tab. Pressing Enter or Space dismisses the toast. |
| Colour contrast | All variant text meets WCAG 2.1 AA (4.5:1 minimum). |
| Colour not sole indicator | Variants pair colour with an icon and title text (e.g., "Error" + red + ✕ icon). |
| Reduced motion | Slide-in animation is disabled when prefers-reduced-motion: reduce is active. |
| Auto-dismiss timing | Minimum 5 000 ms delay. Error toasts should not auto-dismiss. Members can always dismiss manually. |
9. SEO
Transient / structural UI with no indexable content of its own — no SEO markup required. Ensure any content this component wraps or reveals stays server-rendered and crawlable.
10. Analytics
Analytics are captured through the shared data-analytics-component attribute on the component root (emitted automatically) and reported to the central data layer. Event names and payloads follow the organisation's standard analytics schema — defined centrally with the analytics team, not invented per component — so no bespoke tracking is specified here.
11. AEM Notes
- Resource type:
caat/components/toast - Component group: CAAT Components – Feedback
- Proxy: Create as a proxy component under
/apps/caat/components/toast. - Policies: Configure allowed variants and auto-dismiss defaults per template via content policies.
- Sling Model:
com.caat.core.models.ToastModel— exposestitle,body,variant,icon,actionLabel,actionUrl,autohide,delay. - HTL:
toast.html— usesdata-sly-attributeto set variant class and data attributes dynamically. - Client library:
caat.components.toast(categories:caat.site). Includes JS for Bootstrap Toast initialization. - Render condition: Toast is rendered only when triggered by a server-side or client-side event — not displayed in the AEM editor preview by default.
12. Dialog Model (YAML)
Simplified model — shows field intent and Granite UI resource types, not the literal cq:dialog node tree (e.g. select options are authored as child items nodes).
title: Toast
description: Lightweight non-blocking notification for member feedback.
fields:
- name: title
label: Title
type: textfield
required: true
maxLength: 60
helpText: Short header text (e.g., "Success", "Session Expiring").
- name: body
label: Body
type: textarea
required: true
maxLength: 200
helpText: Notification message. Keep concise and actionable.
- name: variant
label: Variant
type: select
required: true
options:
- value: default
label: Default (Blue)
- value: success
label: Success (Green)
- value: warning
label: Warning (Amber)
- value: error
label: Error (Red)
- value: info
label: Info (Blue)
helpText: Determines accent colour and header background.
- name: icon
label: Icon
type: iconpicker
required: false
helpText: Bootstrap Icon for the header (e.g., bi-check-circle-fill).
- name: actionLabel
label: Action Label
type: textfield
required: false
maxLength: 30
helpText: Optional action link text (e.g., "Undo", "View").
- name: actionUrl
label: Action URL
type: pathpicker
required: false
helpText: Destination for the action link. Required if Action Label is set.
- name: autohide
label: Auto-dismiss
type: checkbox
required: false
defaultValue: true
helpText: Automatically hide the toast after the configured delay.
- name: delay
label: Dismiss Delay (ms)
type: numberfield
required: false
defaultValue: 5000
min: 3000
helpText: Time before auto-dismiss. Minimum 3000 ms.
13. QA Acceptance Checklist
- All four colour variants render correct left-border accent and header background.
- Toast appears with slide-in animation from the right.
- Animation is suppressed when
prefers-reduced-motion: reduceis active. - Close button dismisses the toast and receives a visible focus ring on Tab.
- Auto-dismiss hides the toast after the configured delay (default 5 000 ms).
- Error-variant toast does not auto-dismiss by default.
- Action link ("Undo", "View") is keyboard-accessible and announces correctly.
- Screen reader (NVDA, VoiceOver) announces the toast title and body immediately on display.
- Stacked toasts display in the bottom-right corner and stack vertically with spacing.
- No more than 3 toasts visible simultaneously (oldest removed when a 4th is triggered).
- Colour contrast meets WCAG 2.1 AA (4.5:1) for all variants.
- Analytics events (
toast-displayed,toast-dismissed,toast-action-click) fire correctly. - Cross-browser tested: Chrome, Firefox, Safari, Edge.
14. Definition of Done
| Area | Done means |
|---|---|
| Design | Figma component matches this contract. All four variant colours documented with accent tokens. Slide-in animation specified. Stacked layout pattern included. |
| Development | AEM proxy component created. HTL template emits semantic HTML per Section 6. CSS uses design tokens exclusively. JS initializes Bootstrap Toast API. Reduced-motion fallback in place. Unit tests pass. |
| QA | All items in the QA Acceptance Checklist (Section 13) pass. Manual accessibility audit completed. Cross-browser tested (Chrome, Firefox, Safari, Edge). |
| Launch | Component deployed to AEM production. Content authors trained on variant selection and auto-dismiss configuration. Documentation published. Analytics dashboards confirmed receiving events. |