Event created
Friday, October 9 at 10:00 AM.
Feedback
A brief notification in a corner of the screen, announced politely to screen readers.
| Class name | Type | Description |
|---|---|---|
toastplf:toast | Component | The container fixed to the corner |
toast-closeplf:toast-close | Part | The close button, which draws an x while empty |
toast-close-iconplf:toast-close-icon | Part | Your own SVG, in place of the drawn x; an icon class there doesn't need it |
toast-actionplf:toast-action | Part | An action button |
toast-countdownplf:toast-countdown | Part | The time-left bar the script adds |
toast-countdown-trackplf:toast-countdown-track | Part | The countdown bar's track the script adds |
Event created
Friday, October 9 at 10:00 AM.
<button class="btn btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-default">Show toast</button>
<section class="toast" aria-label="Notifications">
<article class="alert shadow-lg" id="toast-default" data-plf-toast hidden>
<div class="alert-content">
<p class="alert-title" data-plf-toast-title>Event created</p>
<p class="alert-description" data-plf-toast-description>Friday, October 9 at 10:00 AM.</p>
</div>
<button class="toast-close" data-plf-trigger="toast:hide"></button>
</article>
</section><button class="plf:btn plf:btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-default">Show toast</button>
<section class="plf:toast" aria-label="Notifications">
<article class="plf:alert plf:shadow-lg" id="toast-default" data-plf-toast hidden>
<div class="plf:alert-content">
<p class="plf:alert-title" data-plf-toast-title>Event created</p>
<p class="plf:alert-description" data-plf-toast-description>Friday, October 9 at 10:00 AM.</p>
</div>
<button class="plf:toast-close" data-plf-trigger="toast:hide"></button>
</article>
</section>'use client';
import { Button, toast, Toaster } from '@pelatform/react';
export function Example() {
function show() {
toast({ title: 'Event created', description: 'Friday, October 9 at 10:00 AM.' });
}
return (
<>
<Button variant="outline" onClick={show}>Show toast</Button>
<Toaster />
</>
);
}'use client';
import { Button, toast, Toaster } from '@pelatform/react/prefixed';
export function Example() {
function show() {
toast({ title: 'Event created', description: 'Friday, October 9 at 10:00 AM.' });
}
return (
<>
<Button variant="outline" onClick={show}>Show toast</Button>
<Toaster />
</>
);
}Showing a message announces it to screen readers without moving focus.
Add data-plf-duration="0" to an error so it stays until it is closed.
Changes saved
Your workspace preferences are up to date.
Couldn't save changes
Check your connection and try again.
<button class="btn btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-success">Show success</button>
<button class="btn btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-error">Show error</button>
<section class="toast" aria-label="Status notifications">
<article class="alert shadow-lg alert-success" id="toast-success" data-plf-toast hidden>
<div class="alert-content">
<p class="alert-title" data-plf-toast-title>Changes saved</p>
<p class="alert-description" data-plf-toast-description>Your workspace preferences are up to date.</p>
</div>
<button class="toast-close" data-plf-trigger="toast:hide"></button>
</article>
<article class="alert shadow-lg alert-error" id="toast-error" data-plf-toast data-plf-duration="0" hidden>
<div class="alert-content">
<p class="alert-title" data-plf-toast-title>Couldn't save changes</p>
<p class="alert-description" data-plf-toast-description>Check your connection and try again.</p>
</div>
<button class="toast-close" data-plf-trigger="toast:hide"></button>
</article>
</section><button class="plf:btn plf:btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-success">Show success</button>
<button class="plf:btn plf:btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-error">Show error</button>
<section class="plf:toast" aria-label="Status notifications">
<article class="plf:alert plf:shadow-lg plf:alert-success" id="toast-success" data-plf-toast hidden>
<div class="plf:alert-content">
<p class="plf:alert-title" data-plf-toast-title>Changes saved</p>
<p class="plf:alert-description" data-plf-toast-description>Your workspace preferences are up to date.</p>
</div>
<button class="plf:toast-close" data-plf-trigger="toast:hide"></button>
</article>
<article class="plf:alert plf:shadow-lg plf:alert-error" id="toast-error" data-plf-toast data-plf-duration="0" hidden>
<div class="plf:alert-content">
<p class="plf:alert-title" data-plf-toast-title>Couldn't save changes</p>
<p class="plf:alert-description" data-plf-toast-description>Check your connection and try again.</p>
</div>
<button class="plf:toast-close" data-plf-trigger="toast:hide"></button>
</article>
</section>'use client';
import { Button, toast, Toaster } from '@pelatform/react';
export function Example() {
function showSuccess() {
toast.success({ title: 'Changes saved', description: 'Your workspace preferences are up to date.' });
}
function showError() {
toast.error({ title: "Couldn't save changes", description: 'Check your connection and try again.', duration: 0 });
}
return (
<>
<Button variant="outline" onClick={showSuccess}>Show success</Button>
<Button variant="outline" onClick={showError}>Show error</Button>
<Toaster />
</>
);
}'use client';
import { Button, toast, Toaster } from '@pelatform/react/prefixed';
export function Example() {
function showSuccess() {
toast.success({ title: 'Changes saved', description: 'Your workspace preferences are up to date.' });
}
function showError() {
toast.error({ title: "Couldn't save changes", description: 'Check your connection and try again.', duration: 0 });
}
return (
<>
<Button variant="outline" onClick={showSuccess}>Show success</Button>
<Button variant="outline" onClick={showError}>Show error</Button>
<Toaster />
</>
);
}A message with an action stays until it is closed. Your click handler runs the action, then the message hides, unless the handler calls preventDefault().
Project archived
You can restore it to your workspace.
<button class="btn btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-action">Archive project</button>
<section class="toast" aria-label="Action notifications">
<article class="alert shadow-lg" id="toast-action" data-plf-toast hidden>
<div class="alert-content">
<p class="alert-title" data-plf-toast-title>Project archived</p>
<p class="alert-description" data-plf-toast-description>You can restore it to your workspace.</p>
</div>
<button class="toast-action" data-plf-toast-action>Undo</button>
<button class="toast-close" data-plf-trigger="toast:hide"></button>
</article>
</section>
<script>
document.querySelector('#toast-action [data-plf-toast-action]').addEventListener('click', () => {
// Undo the change here; the message then hides.
});
</script><button class="plf:btn plf:btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-action">Archive project</button>
<section class="plf:toast" aria-label="Action notifications">
<article class="plf:alert plf:shadow-lg" id="toast-action" data-plf-toast hidden>
<div class="plf:alert-content">
<p class="plf:alert-title" data-plf-toast-title>Project archived</p>
<p class="plf:alert-description" data-plf-toast-description>You can restore it to your workspace.</p>
</div>
<button class="plf:toast-action" data-plf-toast-action>Undo</button>
<button class="plf:toast-close" data-plf-trigger="toast:hide"></button>
</article>
</section>
<script>
document.querySelector('#toast-action [data-plf-toast-action]').addEventListener('click', () => {
// Undo the change here; the message then hides.
});
</script>'use client';
import { Button, toast, Toaster } from '@pelatform/react';
export function Example() {
function archive() {
toast({
title: 'Project archived',
description: 'You can restore it to your workspace.',
action: {
label: 'Undo',
onClick: () => {
// Undo the change here; the message then hides.
},
},
});
}
return (
<>
<Button variant="outline" onClick={archive}>Archive project</Button>
<Toaster />
</>
);
}'use client';
import { Button, toast, Toaster } from '@pelatform/react/prefixed';
export function Example() {
function archive() {
toast({
title: 'Project archived',
description: 'You can restore it to your workspace.',
action: {
label: 'Undo',
onClick: () => {
// Undo the change here; the message then hides.
},
},
});
}
return (
<>
<Button variant="outline" onClick={archive}>Archive project</Button>
<Toaster />
</>
);
}Show a message from your own code with PLF.Toast.show(), such as after a request succeeds: it creates the message, and a toast container in the page’s first root the first time, and removes the message once it hides. PLF.Button.loading() keeps the button busy meanwhile.
<form class="flex flex-col gap-4 max-w-sm" id="toast-form">
<div class="field">
<label class="field-label" for="toast-form-name">Display name</label>
<input class="input" id="toast-form-name" name="name" type="text" autocomplete="name" value="Jordan Rivera">
</div>
<button class="btn btn-primary self-start">
<span class="btn-label">Save profile</span>
<span class="btn-loading">
<span class="btn-icon btn-icon-loading"></span>
Saving…
</span>
</button>
</form>
<script>
const form = document.getElementById('toast-form');
form.addEventListener('submit', async event => {
event.preventDefault();
// Your request; the button shows its loading part until it settles.
const response = await PLF.Button.loading(event.submitter, fetch('/profile', { method: 'POST', body: new FormData(form) }));
if (response.ok) PLF.Toast.show({ title: 'Profile saved', description: 'Your display name is up to date.', color: 'success' });
});
</script><form class="plf:flex plf:flex-col plf:gap-4 plf:max-w-sm" id="toast-form">
<div class="plf:field">
<label class="plf:field-label" for="toast-form-name">Display name</label>
<input class="plf:input" id="toast-form-name" name="name" type="text" autocomplete="name" value="Jordan Rivera">
</div>
<button class="plf:btn plf:btn-primary plf:self-start">
<span class="plf:btn-label">Save profile</span>
<span class="plf:btn-loading">
<span class="plf:btn-icon plf:btn-icon-loading"></span>
Saving…
</span>
</button>
</form>
<script>
const form = document.getElementById('toast-form');
form.addEventListener('submit', async event => {
event.preventDefault();
// Your request; the button shows its loading part until it settles.
const response = await PLF.Button.loading(event.submitter, fetch('/profile', { method: 'POST', body: new FormData(form) }));
if (response.ok) PLF.Toast.show({ title: 'Profile saved', description: 'Your display name is up to date.', color: 'success' });
});
</script>'use client';
import { useState, type FormEvent } from 'react';
import { Button, Field, Input, toast, Toaster } from '@pelatform/react';
export function Example() {
const [saving, setSaving] = useState(false);
async function save(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
setSaving(true);
try {
// Your request; the button shows its loading part until it settles.
const response = await fetch('/profile', { method: 'POST', body: new FormData(event.currentTarget) });
if (response.ok) toast.success({ title: 'Profile saved', description: 'Your display name is up to date.' });
} finally {
setSaving(false);
}
}
return (
<>
<form className="flex flex-col gap-4 max-w-sm" onSubmit={save}>
<Field label="Display name">
<Input name="name" type="text" autoComplete="name" defaultValue="Jordan Rivera" />
</Field>
<Button color="primary" className="self-start" loading={saving} loadingText="Saving…">
Save profile
</Button>
</form>
<Toaster />
</>
);
}'use client';
import { useState, type FormEvent } from 'react';
import { Button, Field, Input, toast, Toaster } from '@pelatform/react/prefixed';
export function Example() {
const [saving, setSaving] = useState(false);
async function save(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
setSaving(true);
try {
// Your request; the button shows its loading part until it settles.
const response = await fetch('/profile', { method: 'POST', body: new FormData(event.currentTarget) });
if (response.ok) toast.success({ title: 'Profile saved', description: 'Your display name is up to date.' });
} finally {
setSaving(false);
}
}
return (
<>
<form className="plf:flex plf:flex-col plf:gap-4 plf:max-w-sm" onSubmit={save}>
<Field label="Display name">
<Input name="name" type="text" autoComplete="name" defaultValue="Jordan Rivera" />
</Field>
<Button color="primary" className="plf:self-start" loading={saving} loadingText="Saving…">
Save profile
</Button>
</form>
<Toaster />
</>
);
}Sync started
Your latest changes are being uploaded.
Export complete
Your report is ready to download.
<button class="btn btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-duration-short">Two seconds</button>
<button class="btn btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-duration-open">Stays open</button>
<section class="toast" aria-label="Timed notifications">
<article class="alert shadow-lg" id="toast-duration-short" data-plf-toast data-plf-duration="2000" hidden>
<div class="alert-content">
<p class="alert-title" data-plf-toast-title>Sync started</p>
<p class="alert-description" data-plf-toast-description>Your latest changes are being uploaded.</p>
</div>
<button class="toast-close" data-plf-trigger="toast:hide"></button>
</article>
<article class="alert shadow-lg alert-success" id="toast-duration-open" data-plf-toast data-plf-duration="0" hidden>
<div class="alert-content">
<p class="alert-title" data-plf-toast-title>Export complete</p>
<p class="alert-description" data-plf-toast-description>Your report is ready to download.</p>
</div>
<button class="toast-close" data-plf-trigger="toast:hide"></button>
</article>
</section><button class="plf:btn plf:btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-duration-short">Two seconds</button>
<button class="plf:btn plf:btn-outline" data-plf-trigger="toast:show" data-plf-target="toast-duration-open">Stays open</button>
<section class="plf:toast" aria-label="Timed notifications">
<article class="plf:alert plf:shadow-lg" id="toast-duration-short" data-plf-toast data-plf-duration="2000" hidden>
<div class="plf:alert-content">
<p class="plf:alert-title" data-plf-toast-title>Sync started</p>
<p class="plf:alert-description" data-plf-toast-description>Your latest changes are being uploaded.</p>
</div>
<button class="plf:toast-close" data-plf-trigger="toast:hide"></button>
</article>
<article class="plf:alert plf:shadow-lg plf:alert-success" id="toast-duration-open" data-plf-toast data-plf-duration="0" hidden>
<div class="plf:alert-content">
<p class="plf:alert-title" data-plf-toast-title>Export complete</p>
<p class="plf:alert-description" data-plf-toast-description>Your report is ready to download.</p>
</div>
<button class="plf:toast-close" data-plf-trigger="toast:hide"></button>
</article>
</section>'use client';
import { Button, toast, Toaster } from '@pelatform/react';
export function Example() {
function showShort() {
toast({ title: 'Sync started', description: 'Your latest changes are being uploaded.', duration: 2000 });
}
function showOpen() {
toast.success({ title: 'Export complete', description: 'Your report is ready to download.', duration: 0 });
}
return (
<>
<Button variant="outline" onClick={showShort}>Two seconds</Button>
<Button variant="outline" onClick={showOpen}>Stays open</Button>
<Toaster />
</>
);
}'use client';
import { Button, toast, Toaster } from '@pelatform/react/prefixed';
export function Example() {
function showShort() {
toast({ title: 'Sync started', description: 'Your latest changes are being uploaded.', duration: 2000 });
}
function showOpen() {
toast.success({ title: 'Export complete', description: 'Your report is ready to download.', duration: 0 });
}
return (
<>
<Button variant="outline" onClick={showShort}>Two seconds</Button>
<Button variant="outline" onClick={showOpen}>Stays open</Button>
<Toaster />
</>
);
}While a modal dialog is open, messages outside it cannot be shown, so give the dialog its own toast container; PLF.Toast.show() does so by itself.
Toast needs JavaScript. The Full script (pelatform-ui.min.js) starts every component on page load, with no code of your own; with ESM imports, call init() yourself, as in Installation. For markup you add later, see Dynamic content.
<link rel="stylesheet" href="pelatform-ui.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.min.css">
<link rel="stylesheet" href="components/button.min.css">
<link rel="stylesheet" href="components/form.min.css">
<link rel="stylesheet" href="components/alert.min.css">
<link rel="stylesheet" href="components/toast.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/toast.min.js" defer></script>
<script src="components/button.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script><link rel="stylesheet" href="pelatform-ui.prefixed.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.prefixed.min.css">
<link rel="stylesheet" href="components/button.prefixed.min.css">
<link rel="stylesheet" href="components/form.prefixed.min.css">
<link rel="stylesheet" href="components/alert.prefixed.min.css">
<link rel="stylesheet" href="components/toast.prefixed.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/toast.min.js" defer></script>
<script src="components/button.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script>| Attribute | Purpose |
|---|---|
data-plf-toast |
The message: an <article> directly in the toast container, a named <section>, with a unique id and hidden; its title names it. The script adds a polite live region to the container for its announcements |
data-plf-toast-title |
The title; exactly one |
data-plf-toast-description |
The description; at most one |
data-plf-toast-action |
An action <button>; at most one. It keeps the message open until it is closed, and hides it after your click handler unless the handler calls preventDefault |
data-plf-duration |
Milliseconds before closing, 5000 by default; 0 keeps the toast open. A timed toast shows a countdown and pauses while hovered or focused |
data-plf-trigger="toast:, "toast: |
On a <button> in the same root and dialog, shows or hides the toast whose id is in data-plf-target; each toast holds one toast: close button, which needs no target and is named Dismiss notification unless it has a name |
| Method | Behavior |
|---|---|
PLF. |
Returns the instance, creating it for valid markup; a numeric options. overrides the attribute |
PLF. |
Returns the instance or null |
PLF. |
Creates and shows a message: its title, and optionally its description, color (success, error, warning or info), duration, action ({label, onClick}) and root; removes it once it hides. While a Modal is open, the message shows inside that dialog and hides when it closes. Returns its instance, or null when it cannot show |
instance. |
Shows the toast; focus returns to the optional trigger if the toast closes while focused. Returns false when canceled, already visible or outside an open modal |
instance. |
Hides the toast; returns false when canceled or already hidden |
instance. |
Returns {visible, paused, duration} |
instance. |
Hides the toast without events and removes listeners and timers |
| Event | When |
|---|---|
plf: |
Before showing; cancelable |
plf: |
After showing |
plf: |
Before hiding; cancelable |
plf: |
After hiding |
Each event’s detail:
| Property | Value |
|---|---|
instance |
The Toast instance |
reason |
api, trigger, escape, timeout or action |
trigger |
The button that showed or hid it, the focused element for escape, or the trigger given to show; otherwise null |
visible |
true for before-show and show, false for before-hide and hide |
| Key | Action |
|---|---|
| Tab, Shift+Tab | Reach the action and close buttons in page order; focus is not trapped |
| Enter, Space | Activates the focused button |
| Escape | Closes the toast that contains focus, through plf: |
Toaster from @pelatform/react shows the messages toast() creates, in the markup PLF.Toast.show() gives them: render it once, as in your layout, and call toast() from any code, such as after a request.
| Prop | Values | Default |
|---|---|---|
aria-label |
The container’s name | Notifications |
closeLabel |
The name of each close button | Dismiss notification |
toast(options), or toast(title), takes PLF.Toast.show()’s options and returns a function that hides the message; toast.success(), toast.error(), toast.warning() and toast.info() set its color.
| Option | Values | Default |
|---|---|---|
title |
The title, announced with the description | Required |
description |
Text under the title | None |
color |
success, error, warning, info |
Neutral |
duration |
Milliseconds before it hides, paused while hovered or focused; 0 keeps it open |
5000, or 0 with an action |
action |
{label, onClick}: onClick runs, then the message hides unless it calls preventDefault |
None |
A call before the Toaster mounts waits for it. While a Modal stays open, the message shows inside that dialog and hides when it closes. Other props are the container <section>’s own, className and ref included.
A message takes Alert’s --plf-alert-* variables and the shadow-lg utility.
| Variable | Default |
|---|---|
--plf-toast-width |
24rem, at most the screen width less the gutters |
--plf-toast-gap |
Space 3 (12px), between and inside messages |