Toast
A short notification card in one shared bottom-right column. Tone rides on the border and text colour.
bunx shadcn@latest add @nalarx/toastUsage
For one message held in parent state, Toast is enough. It dismisses itself after 2.4s, or 3.6s for kind: "err".
import { Toast, type ToastMessage } from "@/components/ui/nx/Toast";
const [toast, setToast] = useState<ToastMessage | null>(null);
setToast({ msg: t("members.invited") });
<Toast toast={toast} onDismiss={() => setToast(null)} />For several cards, a warning, or a card that opens something, compose ToastRegion and ToastCard:
<ToastRegion>
{builds.map((build) => (
<ToastCard
key={build.id}
tone={build.failed ? "warn" : "ok"}
onActivate={() => open(build.id)}
activateLabel={t("dashboards.open", { name: build.name })}
onDismiss={() => dismiss(build.id)}
autoDismissMs={6000}
>
{build.message}
</ToastCard>
))}
</ToastRegion>Every region joins one fixed column on document.body, so toasts from different screens stack instead of covering each other, and a transformed ancestor cannot pull them off screen. The column sits 24px from the bottom-right corner; on phones (under 768px) it moves to the top right, below a 52px app bar, so it does not cover a chat composer.
Tones (ok, err, warn), a card whose body is a button, and one without a dismiss button:
Real toasts in the region; hover one to hold it:
Keyboard
Toasts do not take focus when they appear, and there is no Escape shortcut. The region sits at the end of document.body, so Tab reaches it after the rest of the page: first the card body when it is a button (onActivate), then its Dismiss button. Hover or focus anywhere inside a card holds its auto-dismiss countdown.
A card without onActivate is an <output>, so screen readers announce its text politely.
Props
ToastCard:
| Prop | Type | Default | |
|---|---|---|---|
tone | "ok" | "err" | "warn" | "ok" | warn: not finished, but the reader can still act on it. |
children | ReactNode | The message line. | |
onActivate | () => void | Makes the whole body a button. | |
activateLabel | string | Accessible name of that button. | |
onDismiss | () => void | Shows the Dismiss button. | |
autoDismissMs | number | Calls onDismiss after this long; hover and focus hold it. | |
dismissLabel | string | dismiss string | Visible text of the button. |
dismissAriaLabel | string | dismissNotification string | Its accessible name. |
ToastRegion takes ariaLabel (default: the toastRegion string) and children. Toast takes toast: { msg, kind?: "ok" \| "err" } \| null and onDismiss.
Replaces
Web NxToast.tsx (NxToastRegion, NxToastCard, NxToastTone) and Toast.tsx, and the Platform's own Toast.tsx (top-right, status dot, no dismiss button). The facades keep NxToastRegion, NxToastCard and Toast. Web's unused base/Toast.tsx (Base UI toast manager) is not part of this item.