Toast
Composable notification primitives and default toast chrome used by the platform toast system.
Overview
The shared toast UI is layered:
| Layer | Role |
|---|---|
Toast primitives | Low-level layout and styling pieces |
DefaultToast | Standard composed toast used by platform helpers |
showToast / showPromiseToast | The normal imperative API most product code should use |
This page documents the component layer: the composable toast building blocks and the default toast component they produce.
In most product code, do not build toasts by hand. Use showToast instead. Only drop down to the component layer when you need a special toast layout or when you are extending the notification system itself.
See the toasts patterns page for the normal platform guidance.
Architecture
The toast stack is implemented in shared UI as:
- primitives in
@fsai/shared-ui/src/primitives/Toast/Toast.tsx - composed component exports in
@fsai/shared-ui/src/components/Toast/Toast.tsx - imperative helpers in
@fsai/shared-ui/src/components/Toast/Toast.utils.tsx
The visual default used across the brand dashboard is DefaultToast, not raw react-toastify output.
Basic Composition
import { Toast } from '@fsai/shared-ui';
<Toast type="success">
<Toast.Body>
<Toast.Icon type="success" />
<div className="flex-1 min-w-0">
<Toast.Title type="success">Saved</Toast.Title>
<Toast.Description>Changes were saved successfully.</Toast.Description>
</div>
</Toast.Body>
</Toast>This is the low-level compound API. It is useful when you need custom layout but still want the shared toast styling and semantics.
Default Toast
DefaultToast is the standard composed implementation used by showToast.
It handles:
- type-based icon and styling
- optional title
- description/content area
- optional action buttons
- optional close button
import { DefaultToast } from '@fsai/shared-ui';
<DefaultToast
type="neutral"
title="Lead Deleted"
content="The lead has been deleted"
actions={[
{
text: 'Undo',
onClick: handleUndo,
},
]}
/>Toast Portal
ToastPortal mounts the shared react-toastify container into #toast-root.
In application code, this is usually mounted once near the app root. In the brand dashboard:
index.htmlprovides#toast-rootApp.tsxmounts<ToastPortal />App.tsxalso importsreact-toastify/dist/ReactToastify.css
If the portal or root node is missing, platform toasts will not render.
Compound API
| Export | Purpose |
|---|---|
Toast | Thin wrapper around the primitive container with static subcomponents attached |
Toast.Body | Main horizontal layout row |
Toast.Icon | Type-based icon, with optional icon override |
Toast.Title | Title row with type-aware coloring |
Toast.Description | Secondary text/content area |
Toast.ActionsContainer | Action button row |
Toast.Close | Close affordance |
DefaultToast | Standard ready-to-render composed toast |
ToastPortal | Shared toast container portal |
Primitive Behavior
type
The shared toast types are:
successneutralinfoerror
These control:
- background color
- title color
- default icon
- accessibility semantics
Accessibility behavior comes from the primitive container:
errorusesrole="alert"andaria-live="assertive"- other types use
role="status"andaria-live="polite"
Props
Toast
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'success' | 'neutral' | 'info' | 'error' | — | Required. Visual and semantic toast type. |
children | ReactNode | — | Required. Toast content tree. |
className | string | — | Additional container classes. |
DefaultToast
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'success' | 'neutral' | 'info' | 'error' | — | Required. Toast type. |
content | ReactNode | — | Required. Main toast description/content. |
title | string | — | Optional title above the content. |
actions | { text, onClick, leftAdornment?, rightAdornment? }[] | — | Optional action buttons. |
onClose | () => void | null | — | Optional close handler. |
icon | IconName | — | Optional icon override. |
ToastPortal
ToastPortal does not take props. It renders a shared ToastContainer with platform defaults:
- bottom-right placement
autoClose={10000}- hidden progress bar
- no built-in toastify close button
closeOnClick={false}
When Custom Composition Fits
Reach for the component layer when:
- you are extending the shared toast system itself
- you need custom content but still want shared toast styling
- you need a composed layout that
showToastdoes not express cleanly - you are building a toast that will be rendered through
react-toastifymanually
For example, UploadProgressToast uses a fully custom layout and is updated over time with toast.update(...) rather than rendered through DefaultToast.
Brand Dashboard Usage
Representative usages:
| Pattern | Path | Notes |
|---|---|---|
| App-level container | fsai/apps/brand-dashboard/src/App.tsx | Mounts ToastPortal once for the app. |
| Undoable action toast | fsai/apps/brand-dashboard/src/pages/Leads/Leads.tsx | Uses showToast, which renders DefaultToast with actions. |
| Promise lifecycle toast | fsai/apps/brand-dashboard/src/pages/Analytics/components/AnalyticsReportsDialog/AnalyticsReportsDialog.tsx | Uses showPromiseToast, which still renders DefaultToast. |
| Fully custom progress toast | fsai/apps/brand-dashboard/src/context/UploadContext/UploadContext.tsx | Uses raw react-toastify updates with UploadProgressToast. |
Important Conventions
- Prefer
showToastandshowPromiseToastover manual composition in product code. DefaultToastis the shared default chrome for platform notifications.ToastPortalmust be mounted once at the app level for shared toasts to appear.Toastcomponent docs are about UI composition, not about when a workflow should trigger a toast.- The brand-dashboard
modules/toastarea is for Toast POS integration, not the UI notification component.
Guidelines
- Do use
ToastandDefaultToastwhen you need custom toast rendering infrastructure - Do rely on the shared types and semantics instead of inventing new toast color schemes
- Do keep custom toast layouts compact and notification-sized
- Don't compose raw toast chrome in ordinary feature code when
showToastalready fits - Don't confuse UI toasts with the unrelated Toast POS integration modules