Pho Design System

Notification

A standalone status card — a tinted glyph, a title and one supporting line, an optional confirm action, and an optional close button. It owns its surface but nothing about timing or stacking: use it on its own, or drop it inside a Toast when you want it to appear, stack, and dismiss on its own. For a choice the user must make, use Dialog.

Import

import { Notification } from "@photon-ai/pho-ui/components/notification";

Colors

color is a closed, semantic set — it selects the glyph and its tint together. The brand card below also shows the reduced action row: a confirm link paired with a dismiss link.

New workspace invite

Olivia added you to the Photon team.

Draft saved

Your changes are stored locally.

Deployment ready

photon-web is live in production.

Usage nearing limit

You've used 90% of this month's build minutes.

Deploy failed

The build step exited with code 1.

<Notification
  color="success"
  title="Deployment ready"
  description="photon-web is live in production."
  onClose={() => {}}
/>
color Use it for
brand Informational / product update (default)
gray Neutral, low-stakes note
success An action completed
warning Needs attention, not yet failed
error Something went wrong

Actions and dismissal

Two independent, optional pieces. Passing confirmLabel (with onConfirm) renders the action row: a brand confirm link beside a dismiss link whose text is dismissLabel (default "Dismiss"). Passing onClose renders the top-right close button — and wires the dismiss link, when the row is present, to the same handler. A card with neither is a read-only note.

Deploy failed

The build step exited with code 1.

Deployment ready

photon-web is live in production.

Draft saved

Your changes are stored locally.

// Full row + close button
<Notification
  color="error"
  title="Deploy failed"
  description="The build step exited with code 1."
  confirmLabel="Retry"
  onConfirm={retry}
  onClose={dismiss}
/>

// Close button only
<Notification title="Deployment ready" onClose={dismiss} />

// Read-only note — no actions
<Notification title="Draft saved" description="Stored locally." />

With Toast

The card is not a lifecycle. For a transient, auto-stacking notification, render it as the child of a Toast.Root whose own surface you neutralize (className="bg-transparent shadow-none ring-0") — the Toast manager owns motion, stacking, and swipe-to-dismiss, while the Notification owns the look. Wire the card’s onClose back to manager.close(toast.id).

function ToastList() {
  const manager = Toast.useToastManager();
  return manager.toasts.map((toast) => (
    <Toast.Root
      key={toast.id}
      toast={toast}
      className="bg-transparent shadow-none ring-0"
    >
      <Notification
        color={toast.data?.color ?? "brand"}
        title={toast.title}
        description={toast.description}
        onClose={() => manager.close(toast.id)}
      />
    </Toast.Root>
  ));
}

// Fire one:
manager.add({
  title: "Deployment ready",
  description: "photon-web is live in production.",
  data: { color: "success" },
});

Anatomy

Props

Notification is a single element; extra HTMLAttributes<HTMLDivElement> (such as role, aria-live, id) spread onto its root <div>.

Accessibility

Keyboard:

There is no built-in Esc handler — the card is not a dialog, so dismissal is always an explicit control (or the toast’s swipe).

Best practices