feedback
Toast
A short message that confirms what just happened, at the bottom of the screen, and goes away by itself.
Rich widgetNeeds a script for its behavior.
Usage
Press a button to see a toast. Buttons with data-ca-toast show one without code; apps call toast().
<div class="flex flex-wrap gap-2">
<button class="ca-button ca-button--outline ca-button--md" type="button" data-ca-toast="Lesson moved to Thursday at 09:00" data-ca-toast-tone="success">Move lesson</button>
<button class="ca-button ca-button--outline ca-button--md" type="button" data-ca-toast="Draft saved">Save draft</button>
<button class="ca-button ca-button--outline ca-button--md" type="button" data-ca-toast="Could not send the invoice: the address is missing" data-ca-toast-tone="danger">Send invoice</button>
</div>Examples
Variants
The markup ca-toast.js creates, in every tone. The message says what happened, so it does not rely on color.
<div class="grid w-full max-w-sm gap-2">
<div class="ca-toast ca-toast--neutral">
<p class="ca-toast__message">Draft saved</p>
<button class="ca-toast__close" type="button" aria-label="Dismiss notification">×</button>
</div>
<div class="ca-toast ca-toast--info">
<p class="ca-toast__message">Sam opened the invitation</p>
<button class="ca-toast__close" type="button" aria-label="Dismiss notification">×</button>
</div>
<div class="ca-toast ca-toast--success">
<p class="ca-toast__message">Lesson moved to Thursday</p>
<button class="ca-toast__close" type="button" aria-label="Dismiss notification">×</button>
</div>
<div class="ca-toast ca-toast--warning">
<p class="ca-toast__message">Two lessons still need a car</p>
<button class="ca-toast__close" type="button" aria-label="Dismiss notification">×</button>
</div>
<div class="ca-toast ca-toast--danger">
<p class="ca-toast__message">Could not send the invoice</p>
<button class="ca-toast__close" type="button" aria-label="Dismiss notification">×</button>
</div>
</div>With an action
A toast can carry one action, such as Undo. It then stays until it is closed.
<div class="ca-toast ca-toast--neutral w-full max-w-sm">
<p class="ca-toast__message">Lesson cancelled</p>
<button class="ca-button ca-button--secondary ca-button--sm" type="button">Undo</button>
<button class="ca-toast__close" type="button" aria-label="Dismiss notification">×</button>
</div>Guidance and accessibility
When to use
- Use a toast to confirm an action people just took, such as moving a lesson, when the page itself does not show the result.
- Keep it to one short sentence that says what happened.
- Do not use a toast for something people must read or act on. Errors in a form belong next to the field; a decision belongs in a dialog.
Show a toast from code
import { toast } from "@calaca/ui/behavior/toast";
toast("Lesson moved to Thursday", { tone: "success" });
const close = toast("Lesson cancelled", {
action: { label: "Undo", onClick: () => restoreLesson() },
});toast() returns a function that closes the toast. Options are tone,
duration in milliseconds (5000 by default, Infinity to keep it) and one
action. Without a bundler, import it from ca-toast.js, or dispatch
new CustomEvent("ca:toast", { detail: { message, tone } }) on the document.
Accessibility
- Every message is announced through one
role="status"region that exists before the first toast, so screen readers read each one without moving focus. - A toast stays while the pointer is over it or focus is inside it, and a toast with an action stays until it is closed, so there is time to use the action (WCAG 2.2.1).
- The region is in the top layer. While a modal dialog is open, the page behind it is inert, so the script moves the region into the dialog; toasts then show above it and their buttons work. It moves back when the dialog closes.
- Every toast has a close button with an accessible name.
Classes
Generated from the component contract. Parts use __, modifiers use --.
| Class | Kind | Use it for |
|---|---|---|
ca-toast | Component | One message with its close button. |
ca-toast__region | Part | The region at the bottom end of the screen that holds the toasts; a manual popover. |
ca-toast__message | Part | The text of the message. |
ca-toast__close | Part | The button that closes the toast. |
ca-toast__status | Part | The visually hidden live region that announces each message. |
ca-toast--neutral | Variant | General feedback, such as a saved draft. |
ca-toast--info | Variant | News about something else, such as someone opening an invitation. |
ca-toast--success | Variant | An action worked. |
ca-toast--warning | Variant | It worked, but something needs attention. |
ca-toast--danger | Variant | An action failed. |
Skins
The same markup, dressed by each skin. Structure and behavior stay the same; only the look changes.
Base skin
Neutral grayscale starting point; product skins extend it and change what differs.
Calaca skin
The Calaca UI brand: hueso paper and tinta ink, cempasúchil marigold, rosa and jade.
Proof skin
Pilot skin pushed far from base: square, heavy, offset shadows, larger targets.
Crossview skin
The CrossView proofing table: cool ground, bond-paper sheets, rule-grey hairlines, one red mark.
Framework notes
Link the prebuilt stylesheet of your skin next to your brand theme. No build step.
<link rel="stylesheet" href="theme.css" />
<link rel="stylesheet" href="ca-base.css" />In Astro, Vite and other Tailwind projects, import Calaca after Tailwind and your theme in your main stylesheet.
@import "tailwindcss";
@import "./theme.css";
@import "@calaca/ui/core.css";
@import "@calaca/ui/skins/base.css";Same stylesheet as above; write the classes in className.
<button className="ca-button ca-button--primary ca-button--md" type="button">Save changes</button>Load the toast script once per page. In Astro, Next.js or React, import toast from @calaca/ui/behavior/toast and call it; in plain HTML, import it from ca-toast.js or dispatch a ca:toast event.
<script type="module">
import { toast } from "/calaca/ca-toast.js";
toast("Lesson moved to Thursday", { tone: "success" });
</script>