Feedback
Toast
Brief news about something that just happened, shown without interrupting.
Installation
npx sinaui add toastCopy the src/lib/ui/toast/ folder, Button.svelte, Icon.svelte and tokens.css, and add <Toaster /> once to your root layout.
Then call toast() from anywhere.
Examples
Default
For news that needs no color. Hover or focus a toast and its timer pauses.
<script lang="ts">
import Button from '#lib/ui/Button.svelte';
import { toast } from '#lib/ui/toast/index.js';
</script>
<!-- Add <Toaster /> once, in your root layout. -->
<Button variant="secondary" onclick={() => toast('Manuscript added to your reading list.')}>
Show a toast
</Button>Success
When something worked, with a line of detail.
<script lang="ts">
import Button from '#lib/ui/Button.svelte';
import { toast } from '#lib/ui/toast/index.js';
</script>
<!-- Add <Toaster /> once, in your root layout. -->
<Button
variant="secondary"
onclick={() =>
toast.success('Copy commissioned', {
description: 'A scribe in Baghdad will finish it within the season.'
})}
>
Commission a copy
</Button>Error
When something failed: say what happened and what to do.
<script lang="ts">
import Button from '#lib/ui/Button.svelte';
import { toast } from '#lib/ui/toast/index.js';
</script>
<!-- Add <Toaster /> once, in your root layout. -->
<Button
variant="secondary"
onclick={() =>
toast.error('The Córdoba library is closed for the night.', {
description: 'Requests reopen at dawn prayer.'
})}
>
Send to Córdoba
</Button>With an action
One action, such as Undo. Toasts with an action stay twice as long.
3 loans active
<script lang="ts">
import Button from '#lib/ui/Button.svelte';
import { toast } from '#lib/ui/toast/index.js';
let loans = $state(3);
function withdraw() {
loans -= 1;
toast('Loan withdrawn.', { action: { label: 'Undo', onclick: () => (loans += 1) } });
}
</script>
<Button variant="danger" onclick={withdraw} disabled={loans === 0}>Withdraw a loan</Button>
<p class="count" role="status">{loans} loans active</p>
<style>
.count {
margin: 0;
color: var(--ui-muted);
}
</style>API
| Call | Does |
|---|---|
toast(message, options?) | Shows a toast; returns its id. |
toast.success(…) / toast.error(…) | With an icon, and the kind spoken to screen readers. |
dismiss(id) | Removes one early. |
options | description, action: { label, onclick }, duration (ms) |
Accessibility
- Toasts live in a labeled region that's always in the page, so screen readers announce each one politely without moving focus.
- The countdown pauses while any toast is hovered or focused and while the tab is hidden (WCAG 2.2.1); errors stay 8 seconds, others 5, doubled when there's an action.
- Every toast has a close button. Anything people must act on belongs in a Dialog, not a toast.
- Closing a focused toast moves focus to the next one, or back to where you were: it never drops to the top of the page.
- Enter, exit and restacking move with transforms only, and switch off with reduced motion.
| Key | Action |
|---|---|
| F6 | Jumps to the newest toast, and back to where you were. |
| Tab | Moves between a toast's buttons and on to the next toast. |