Notification v2

A status banner that reports what just happened.

Backup complete
412 files synced to Dropbox a moment ago.
Installation
$Terminal
npx shadcn@latest add https://sdk-components.thesqd.com/r/notification.json
Usage
Same flat props as Alert — icon, title, description, and an optional async action button.
TSImport
import { Notification, NotificationStack } from "@/components/ui/notification";
TSExample
import { CloudArrowUp } from "@phosphor-icons/react/ssr";
import { Notification } from "@/components/ui/notification";

export function Example() {
  return (
    <Notification
      variant="brand"
      icon={<CloudArrowUp weight="duotone" />}
      title="Backup complete"
      description="412 files synced to Dropbox a moment ago."
      actionButton={{ label: "View files" }}
    />
  );
}
Composition
Anatomy of the Notification primitive and the stack.
Notification                     (single component — pass everything as props)
├── version="v1 | v2"            (v2 default — card + accent bar · v1 pill)
├── variant="default | brand | info | success | warning | destructive"
├── icon={<PhosphorIcon weight="duotone" />}
├── title={<ReactNode>}
├── description={<ReactNode>}
├── action={<Button … />}         (optional — top-right slot)
└── actionButton={{ label, loadingLabel?, doneLabel?, successMessage?, variant?, onAction? }}

NotificationStack                (a deck of notifications, newest first)
├── items={[{ id, variant, icon, title, description, actionButton? }, …]}
└── version="v1 | v2"            (applies to every banner in the deck)

notification({ … })              (same content, fired as a Sonner toast)
└── { title, description?, variant?, version?, icon?, actionButton?, duration?, id? }
Brand
The default tone, using the brand primary accent.
Backup complete
412 files synced to Dropbox a moment ago.
Default
Neutral accent for routine, tone-free confirmations.
Copied to clipboard
The install command is on your clipboard.
Info
For neutral, informational context.
New version available
Refresh to pick up the latest build.
Success
Confirms a completed action.
File uploaded successfully
brand-guide.pdf is now available in your files.
Warning
Highlights a recoverable problem or caution.
Your session will expire in 5 minutes
Save your work — we'll sign you out after that.
Destructive
Communicates an error or failed operation.
Upload failed
Something went wrong. Try again or use a different file.
Action button
Pass `actionButton` to pin an async button to the right edge. Click → Spinner + `loadingLabel` → `doneLabel` plus the optional `successMessage` toast. Throwing from `onAction` resets it to idle so the user can retry.
Upload failed
The connection dropped partway through. Retry to finish.
Toast
`notification(...)` fires the same content as a Sonner toast instead of an inline banner — same tone vocabulary, same `actionButton` config, and the same `version`. In v2 the toast renders the Notification surface itself, so a toast and an inline banner are identical. Mount `<Toaster />` once in your layout.
Stack
`NotificationStack` decks them sonner-style: the newest rises into place, older ones scale and blur back, and hovering spreads the deck into a column. Push a few in a row to see the fourth slide out the back.
Deploy finished
squad-ui-2 is live on production.
Build queued
Waiting on an available runner.
Commit pushed
main · 5b366a0
API Reference
Props exposed by the Notification component.
PropTypeDefaultDescription
version"v1" | "v2""v2"Visual treatment. `v2` (default, latest) is the Alert v2 surface — a neutral card with a colored left accent bar and colored icon. `v1` is the older pill.
variant"default" | "brand" | "info" | "success" | "warning" | "destructive""default"Tone. Drives the accent bar and icon color in v2, the border and icon in v1.
iconReactNode—Leading icon. Pass a Phosphor icon with `weight="duotone"` — the component colors it from `variant`.
titleReactNode—Bold heading rendered next to the icon.
descriptionReactNode—Body content. Accepts strings or JSX.
actionButtonAlertActionConfig—Async action button, vertically centered on the right edge. Pass `{ label, loadingLabel?, doneLabel?, successMessage?, variant?, onAction? }`. The notification drives idle → loading (Spinner) → done and fires the optional info toast on resolve.
actionReactNode—Optional content pinned to the top-right corner.
classNamestring—Override or extend the resolved variant classes.
notification()
Options accepted by the imperative toast helper.
PropTypeDefaultDescription
version"v1" | "v2""v2"`v2` renders the Notification v2 surface inside the toast — identical to the inline banner. `v1` uses sonner's own per-tone styling.
titleReactNode—Toast heading. The only required field.
descriptionReactNode—Secondary line under the title.
variant"default" | "brand" | "info" | "success" | "warning" | "destructive""default"Tone — routes to the matching sonner method and sets the default action-button color.
iconReactNode—Leading icon. Size it `size-4` to match sonner's slot.
actionButtonAlertActionConfig—Renders an async action button under the description and dismisses the toast once it resolves. Supplying it defaults `duration` to `Infinity`.
durationnumber—Override sonner's default duration (ms).
idstring | number—Stable id — pass the same one to update an open toast in place. `notification.dismiss(id)` closes it.
toastOptionsExternalToast—Pass-through sonner overrides (classNames, position, …).
NotificationStack
Props exposed by the stacked deck.
PropTypeDefaultDescription
itemsNotificationStackItem[]—Newest first — index 0 sits at the front of the deck. Each item is a `Notification` prop bag plus a stable `id`. Items 1 and 2 peek out behind the front one; a 4th renders as the exit frame. Anything past four is dropped.
classNamestring—Extends the `.t-stack` root (sizing, positioning).