Toast
Dismissible notification component with automatic timeout, an addToast() queue via Toaster, and shorthand header/body/footer props.
A toast is a sm notification surface, modeled on the push notifications native to mobile and desktop operating systems. It's positioned and stacked with flexbox, so alignment follows the same margin and flexbox utility classes as the rest of Chassis.
Overview
<Toast> renders a single notification. Nothing shows until you ask for it.
- Toasts are opt-in — nothing renders until
visibleordefaultVisibleis set, oraddToast()pushes one into aToaster's queue. defaultVisibleshows a toast that then hides itself: by its close button,autohide, orclose.visiblemakes it controlled: those become requests, reported toonVisibleChange(false), and the toast hides when you setvisibletofalse. A state setter fits as it is:visible={open} onVisibleChange={setOpen}.onClosefires after the toast has hidden.- A toast automatically hides after
delaymilliseconds unlessautohideis set tofalse. The countdown pauses while the pointer is over the toast or focus is within it, and only resumes once both leave. - Use
role="status"(the default) for routine confirmations and informational updates. Reserverole="alert"for errors and messages requiring immediate attention. Both roles carry implicit live-region semantics, so no separatearia-liveprop is needed. - The
icon/title/time/message/footer/closeButtonprops are shorthand for the manualToastHeader/ToastBody/ToastFootercomposition — reach for manual composition only when a toast needs more than one header/body/footer block. See Shorthand props. - To dismiss a toast from custom markup — a "Close" button in the footer, a custom icon in the
header — either pass a function to
footerto receiveclosedirectly (see Action footer), or calluseToast()from any child component and wire itscloseto an element'sonClick.
Examples
Basic layout
A toast typically pairs a header and body — the header uses display: flex, aligning icon,
title, and timestamp content with the margin and flexbox utility classes.
A toast needs very little required markup: at minimum, a single element containing its content. A dismiss button is recommended but not enforced.
import { Toast, ToastBody, ToastHeader, Icon } from '@chassis-ui/react'
export const Example = () => {
const icon = <Icon name="info-circle-solid" />
return (
<Toast defaultVisible autohide={false}>
<ToastHeader icon={icon} time="7 min ago" closeButton>
Chassis
</ToastHeader>
<ToastBody>Hello, world! This is a toast message.</ToastBody>
</Toast>
)
}For dynamic notifications, call addToast() from anywhere — an event handler, an async callback —
to push a toast into a Toaster's queue. Toaster renders whatever's currently queued; nothing
else needs to know about it.
import { Button, ToastBody, ToastHeader, Toaster, addToast, Icon } from '@chassis-ui/react'
export const Example = () => {
const icon = <Icon name="info-circle-solid" />
const handleClick = () => {
addToast(
<>
<ToastHeader icon={icon} time="7 min ago" closeButton>
Chassis
</ToastHeader>
<ToastBody>Hello, world! This is a toast message.</ToastBody>
</>
)
}
return (
<>
<Button onClick={handleClick}>Send a toast</Button>
<Toaster placement="bottom-end" />
</>
)
}Shorthand props
For the common case — an icon, a heading, a timestamp, one block of message text —
icon/title/time/message render the same markup as composing ToastHeader/ToastBody by
hand, without the wiring. icon accepts an icon name (rendered via ToastIcon) or any other node
for a fully custom icon, such as a logo or avatar. Add footer for a single row of trailing
content (shorthand for ToastFooter), and closeButton/closeLabel for the dismiss control and
its accessible name. closeButton follows whatever header content is set: it lands in the header
when icon/title/time is present, otherwise alongside message in the body — so a title-less
toast never gets a header that exists only to hold a close button. When both title and message
are set, the toast's aria-labelledby/aria-describedby are wired to them automatically. icon
is hidden from assistive technology by default, since it duplicates title visually.
import { Toast, Icon } from '@chassis-ui/react'
export const Example = () => {
const icon = <Icon name="info-circle-solid" />
return (
<Toast
animation={false}
autohide={false}
defaultVisible
icon={icon}
title="Chassis"
time="7 min ago"
message="Hello, world! This is a toast message."
closeButton
/>
)
}icon/title/time/message/footer are additive with children — for multi-block content
(more than one header, body, or footer region), compose ToastHeader/ToastBody/ToastFooter
manually instead, as in the sections below. ToastHeader itself takes the same shorthand shape —
icon/time as props, the heading as children — so manual composition never requires
hand-writing the <strong>/<span> markup.
Action footer
Add a ToastFooter below the body to hold acknowledgement or follow-up actions, or pass footer
for the same result without composing ToastFooter by hand — it renders .toast-footer,
separated from the body by a border that matches the header rule.
A "Close" action is just a normal Button. Passing a function to footer provides close as its
argument, so a button can wire it straight to onClick without a child component calling
useToast() itself — useful when the footer's only custom need is the close handler. For anything
with its own local state or logic, calling useToast() from a child component works the same way,
and is the only option outside footer (a custom icon in the header, for example).
import { Button, Toast, ToastBody } from '@chassis-ui/react'
export const Example = () => {
return (
<Toast
autohide={false}
defaultVisible
footer={(close) => (
<>
<Button type="button" color="primary" size="sm">
Take action
</Button>
<Button type="button" size="sm" onClick={close}>
Close
</Button>
</>
)}
>
<ToastBody>Hello, world! This is a toast message.</ToastBody>
</Toast>
)
}Translucent
Add translucent to blend the toast in with what's below it.
import { Toast, ToastBody, ToastHeader, Icon } from '@chassis-ui/react'
export const Example = () => {
const icon = <Icon name="info-circle-solid" />
return (
<Toast translucent autohide={false} defaultVisible>
<ToastHeader icon={icon} time="7 min ago" closeButton>
Chassis
</ToastHeader>
<ToastBody>Hello, world! This is a toast message.</ToastBody>
</Toast>
)
}Stacking
Wrapping toasts in a Toaster stacks them, adding vertical spacing between each automatically.
import { Toast, ToastBody, ToastHeader, Toaster, Icon } from '@chassis-ui/react'
export const Example = () => {
const icon = <Icon name="info-circle-solid" />
return (
<Toaster>
<Toast autohide={false} defaultVisible>
<ToastHeader icon={icon} time="7 min ago" closeButton>
Chassis
</ToastHeader>
<ToastBody>Hello, world! This is a toast message.</ToastBody>
</Toast>
<Toast autohide={false} defaultVisible>
<ToastHeader icon={icon} time="7 min ago" closeButton>
Chassis
</ToastHeader>
<ToastBody>Hello, world! This is a toast message.</ToastBody>
</Toast>
</Toaster>
)
}Simplified layout
Toast sub-components can be omitted or adjusted with props to simplify the layout. This example
removes the default <ToastHeader> and adds closeButton directly to <ToastBody>, so no manual
markup is needed to lay out the dismiss control.
import { Toast } from '@chassis-ui/react'
export const Example = () => {
return (
<Toast autohide={false} defaultVisible>
Hello, world! This is a toast message.
</Toast>
)
}Color schemes
Apply color and add solid for a full-color background with inverted text — the example below
sets color="primary" and solid on the <Toast>.
import { Toast, ToastBody } from '@chassis-ui/react'
export const Example = () => {
return (
<Toast autohide={false} defaultVisible color="primary" solid>
<ToastBody closeButton>Hello, world! This is a toast message.</ToastBody>
</Toast>
)
}API
Toast
| Prop | Type | Default |
|---|---|---|
animation? | boolean | true |
| Apply a CSS fade transition to the toast. | ||
autohide? | boolean | true |
| Auto hide the toast. The timer starts once the show transition completes and pauses while the pointer is over the toast or focus is within it. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
closeButton? | boolean | — |
Adds a close button — shorthand for ToastHeader's/ToastBody's closeButton prop.
Placed in the header when icon/title/time is set; otherwise placed in the body
alongside message, or in a header containing only the close button if message is
also unset. | ||
closeLabel? | string | — |
Overrides the close button's accessible name (defaults to 'Close'). Set this for
non-English UIs. Shorthand for ToastHeader's closeLabel prop. | ||
color? | ContextColor | — |
| Sets the color of the component to one of Chassis context colors. | ||
defaultVisible? | boolean | false |
Whether the toast is shown when it first renders. Such a toast is uncontrolled: its close
button and the autohide timer hide it. Use visible to show and hide it from outside. | ||
delay? | number | 5000 |
| Delay hiding the toast (ms). | ||
footer? | ReactNode | ((close: () => void) => ReactNode) | — |
Trailing content — typically a row of Buttons — rendered via a single ToastFooter,
after message/children. Pass a function to receive close directly, instead of
calling useToast() from a child component to wire up a "Close" action. | ||
icon? | ReactNode | — |
Leading icon for the header. A string is an icon name, rendered like
<ToastIcon name={icon} /> (or by IconProvider's component); pass
any other node for a fully custom icon (typically a logo or avatar). Shorthand for
ToastHeader's icon prop; hidden from assistive technology by default, since it
duplicates title visually. | ||
message? | ReactNode | — |
Message body, rendered via a single ToastBody. For multi-block content, compose
children manually instead — message wraps everything in one element. | ||
onClose? | (() => void) | — |
| Callback fired once the toast has hidden: after its exit transition. | ||
onShow? | (() => void) | — |
| Callback fired when the toast starts to show. | ||
onVisibleChange? | ((visible: boolean) => void) | — |
Callback fired with false when the toast asks to hide: its close button, close from
useToast or footer, or the autohide timer. With visible set, the toast hides only
when visible becomes false. | ||
role? | "status" | "alert" | status |
ARIA live-region role. Use status (the default) for confirmation, progress, and
informational messages, which announce politely. Use alert for messages that need
immediate attention — validation errors, failed operations — which interrupt speech. | ||
solid? | boolean | — |
Apply a full-color background with inverted text. Only meaningful alongside color. | ||
time? | ReactNode | — |
Header timestamp, rendered after title. Shorthand for ToastHeader's time prop. | ||
title? | ReactNode | — |
Header heading, rendered before time. Shorthand for ToastHeader's children. When set
alongside message, wires the toast's aria-labelledby/aria-describedby to them
automatically. | ||
translucent? | boolean | — |
| Apply a semi-transparent background. | ||
visible? | boolean | — |
Whether the toast is shown. Setting it makes the toast controlled: it hides only when this
becomes false, so pair it with onVisibleChange. Without either visible or
defaultVisible a toast renders nothing. | ||
ToastHeader
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
children? | ReactNode | — |
Heading, rendered before time as a <strong>. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
closeButton? | boolean | — |
| Automatically add a close button to the header. | ||
closeLabel? | string | — |
Overrides the close button's accessible name (defaults to 'Close'). Set this for
non-English UIs. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
icon? | ReactNode | — |
Leading icon. A string is an icon name, rendered like <ToastIcon name={icon} /> (or by
IconProvider's component) and hidden from
assistive technology by default, since it duplicates the heading visually. Pass any other
node for a fully custom icon (typically a logo or avatar) — a custom node is left as-is,
since it may carry its own meaningful accessible name (e.g. an avatar's alt text). | ||
ref? | any | — |
time? | ReactNode | — |
| Trailing timestamp, rendered after the heading. | ||
titleId? | string | — |
Sets the id on the rendered heading element, for aria-labelledby wiring. Set
automatically by Toast when both title and message are used together; only needed
here for manual wiring in a fully custom composition. | ||
ToastIcon
| Prop | Type | Default |
|---|---|---|
className? | string | — |
| A string of all className you want applied to the component. A string of all className you want applied to the base component. | ||
font? | boolean | — |
name | string | — |
Icon name, e.g. folder-tree. Matches an id in the SVG sprite, or a cx-{name} font glyph
class in font mode (see IconProvider's fontPrefix). | ||
size? | string | number | — |
Icon size: a number of pixels, or any CSS length ('1.25rem', '1em'). Sets chassis-css's
--cx-icon-size on the icon, so it applies in font mode too. Leave unset to keep the size
chassis-css gives icons in context (inside a button, an input, a navbar toggler, ...). | ||
sprite? | string | — |
URL of the SVG sprite file. Defaults to IconProvider's sprite, or to none — a sprite
embedded in the page, referenced as #name. Ignored in font mode. | ||
title? | string | — |
| Accessible name. When set, the icon is exposed to assistive tech instead of hidden. | ||
ToastBody
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
closeButton? | boolean | — |
Adds a close button alongside the body content, so a toast composed without a
ToastHeader still gets a dismiss control without any manual layout markup. | ||
closeLabel? | string | — |
Overrides the close button's accessible name (defaults to 'Close'). Set this for
non-English UIs. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
ref? | any | — |
ToastFooter
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
ref? | any | — |
Toaster
| Prop | Type | Default |
|---|---|---|
aria-label? | string | — |
Overrides the toast region's accessible name (defaults to 'Notifications', per
react-aria). Set this for non-English UIs, or to distinguish multiple toasters on the
same page. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
placement? | 'top-start' | 'top-center' | 'top-end' | 'middle-start' | 'middle-center' | 'middle-end' | 'bottom-start' | 'bottom-center' | 'bottom-end' | string | — |
| Describes the placement of your component. | ||