ComponentsToast
Toast
componentTransient confirmations — the toned variants and the actionable snackbar.
Toast
Trigger a sample notification.
Best practices
Do
- A passive confirmation uses the toned variants (.toast--success/info/warn/error) and auto-dismisses.
- An actionable toast ('Saved — Undo') is the snackbar: .toast--snackbar on the inverse surface, ONE .toast__action, one at a time.
- Anchor the stack in one corner via .toast-stack and cap it at about three visible.
Don't
- Don't use a toast for anything that needs a decision — that is a .dialog.
- Don't auto-dismiss a toast that carries an action.
Trigger a toast above ↑
Best practices
Do
- A passive confirmation uses the toned variants (.toast--success/info/warn/error) and auto-dismisses.
- An actionable toast ('Saved — Undo') is the snackbar: .toast--snackbar on the inverse surface, ONE .toast__action, one at a time.
- Anchor the stack in one corner via .toast-stack and cap it at about three visible.
Don't
- Don't use a toast for anything that needs a decision — that is a .dialog.
- Don't auto-dismiss a toast that carries an action.
Recipe CSS
This is the exact CSS your kit ships for Toast — token-driven, so it re-themes with every knob. Get it (and the rest) from the configurator's Use kit panel.
/* === Toast stack ===
In production this stack pins bottom-right of the viewport (use position:
fixed + bottom/right). In the gallery demo it lives inside a bordered
.toast-demo-frame with trigger buttons — clearly a sandbox, not chrome.
The tone-coded left border + dismiss button are the actual pattern;
positioning is a consumer concern, not a token concern. */
.toast-demo-frame {
position: relative;
min-height: 110px;
border: 1px dashed var(--k-border);
border-radius: var(--k-radius-md);
background: var(--k-surface-sunken);
padding: var(--k-s-10);
display: flex;
align-items: flex-end;
overflow: hidden;
}
.toast-demo-frame__empty {
position: absolute;
inset: 0;
display: grid;
place-items: center;
font-size: var(--k-type-eyebrow);
color: var(--k-fg-faint);
pointer-events: none;
}
.toast-stack {
display: flex;
flex-direction: column-reverse;
gap: var(--k-s-6);
align-items: stretch;
width: 100%;
}
.toast {
display: flex;
align-items: flex-start;
gap: var(--k-s-10);
padding: var(--k-s-10) var(--k-s-12);
background: var(--k-surface-overlay, var(--k-surface-raised));
border: var(--k-hairline, 1px solid var(--k-border));
border-radius: var(--k-radius-md);
box-shadow: var(--k-shadow-md);
font-size: var(--k-type-small);
animation: var(--k-anim-slide-up, k-slide-up 240ms ease) backwards;
}
.toast--success { border-left: 3px solid var(--k-success); }
.toast--info { border-left: 3px solid var(--k-info); }
.toast--warn { border-left: 3px solid var(--k-warning); }
.toast--error { border-left: 3px solid var(--k-danger); }
.toast__body { flex: 1; min-width: 0; }
.toast__title { font-weight: var(--k-weight-semibold); }
.toast__sub { color: var(--k-fg-muted); font-size: var(--k-type-small); margin-top: 1px; }
.toast__close {
background: transparent;
border: 0;
padding: var(--k-s-2);
cursor: pointer;
color: var(--k-fg-muted);
display: inline-flex;
border-radius: var(--k-radius-md);
transition: background var(--k-dur-fast, 120ms) var(--k-ease, ease), opacity var(--k-dur-fast, 120ms) var(--k-ease, ease), color var(--k-dur-fast, 120ms) var(--k-ease, ease);
}
.toast__close:hover { color: var(--k-fg); background: var(--k-state-hover); }
/* Inline text action ("Undo", "Retry") — sits after the body, before the
dismiss ✕. On a regular toast it's primary-tinted; the snackbar recolors
it below. NEVER make the action "Dismiss" — that's what the ✕ is for. */
.toast__action {
background: none;
border: 0;
padding: var(--k-s-2) var(--k-s-6);
border-radius: var(--k-radius-sm, 6px);
font: inherit;
font-size: var(--k-type-small);
font-weight: var(--k-weight-semibold);
color: var(--k-primary);
cursor: pointer;
flex: none;
}
.toast__action:hover { background: var(--k-state-hover); }
/* Snackbar (H4) — the M3 snackbar CONTRACT on the toast primitive. Look:
INVERSE surface (the H1 inverse roles — guaranteed contrast on any theme),
no tone border (a snackbar is neutral app feedback, not a status), one
optional text action in inverse-primary. Behavior contract (consumer-
owned): one line, ONE action max, auto-dismiss 4-10s, and one snackbar at
a time — queue them, never stack. */
.toast--snackbar {
background: var(--k-inverse-surface);
color: var(--k-inverse-fg);
border-color: transparent;
align-items: center;
}
.toast--snackbar .toast__sub { color: var(--k-inverse-fg); opacity: 0.72; }
.toast--snackbar .toast__action { color: var(--k-inverse-primary); }
.toast--snackbar .toast__action:hover { background: transparent; text-decoration: underline; text-underline-offset: 3px; }
.toast--snackbar .toast__close { color: var(--k-inverse-fg); opacity: 0.75; }
.toast--snackbar .toast__close:hover { color: var(--k-inverse-fg); background: transparent; opacity: 1; }