f-ui
Design

Messaging Surfaces

Which surface owns a message — field chrome, Message Popover, toast, Notification Center, or a task list page. Five classes, one owner each.

Every enterprise system eventually grows five different ways to tell someone something. They look alike (icon, text, count, list) and they are not interchangeable. Pick the class first, then the component.

The mistake this page prevents: reusing Message Popover as a notification bell, or reusing Notification Center for form validation.

The Five Classes

ClassSubjectLives untilScopeSurface
Field messageone field or one regionresolvedcurrent formForm Item chrome, Form Error Summary, Editable Error Rollup
Object messagethe object on screen right nowsaved or navigated awaycurrent pageMessage Popover
Transient feedbackthe action just takenseconds, dies on navigationcurrent pagehost toast (sonner)
Notificationactivity elsewhere that concerns medismissed by the usercross-app, cross-sessionNotification Center
Taskwork assigned to me that must be completedprocessed by a workflowcross-app, durable, auditablea list page + object page

Two boundaries do the real work.

Object message vs notification. An object message is about the thing on screen and dies when the object is saved. A notification is about something elsewhere and survives navigation, reload, and logout. SAP restricts notification list items to the shell notifications popover for exactly this reason; Salesforce states the converse as a prohibition — do not use notifications as a feedback mechanism.

Notification vs task. A notification is awareness and is disposable. A task is work and is not. Dismissing a notification does not complete the underlying work.

Decision Tree

Is the message about a field the user is editing?
├─ Yes → Form Item chrome (+ one summary: Form Error Summary or Editable Error Rollup)
└─ No
   ├─ Is it about the object currently on screen (readiness to save/submit)?
   │  └─ Yes → Message Popover in the footer toolbar
   ├─ Did the user just take an action and only needs confirmation?
   │  └─ Yes → toast (host-owned), dies on navigation
   ├─ Is it activity elsewhere that concerns this user?
   │  └─ Yes → Notification Center (bell + panel)
   └─ Is it work assigned to this user that must be completed and audited?
      └─ Yes → a list page (QueryList) + object page — not a popover

Hard Rules

  1. Message Popover is never a bell. Its items die with the object. A bell's items outlive the page.
  2. Notification Center is never form validation and never post-action feedback. Errors on the form belong to field chrome and one summary; "Saved" belongs to a toast.
  3. Dismissing a notification does not complete the underlying work. The row disappears; the approval, export, or task behind it still needs processing. Say this in your product copy when dismissal is destructive-looking.
  4. Unseen ≠ unread. The bell badge counts what arrived since the panel was last opened, and clears on open. Read state is per item and is cleared by the user. Do not drive one from the other.
  5. One-step actions only inside a notification. Approve / Reject / Download. Anything multi-step opens the object page.

What We Do Not Ship

Not a componentWhyBuild it with
Task Center / InboxThe industry ships the task class as an application, not a widget. SAP's My Inbox is a list + detail floorplan with search, filter, group by priority/due date/type, claim, forward, mass action, substitution, and an Outbox — that is a page, not a popover.QueryList list page + object page + Comment; see Approval And Case Patterns
Kit ToasterToast is a host concern with no kit design decision. Carbon and Fluent both pair toast with a notification center rather than replacing one with the other — a toast is only safely dismissible because the center keeps the history.sonner, mounted once at the app root, positioned in the same corner as the notification panel
A second severity listOne error owner per class.See Form Validation and Object Messaging And Table Chrome

Counts And Badges

Numeric overlays on a bell or avatar use Count Badge — never a Status Tag, Label Tag, or shadcn Badge with text. See Tag Selection.

The count itself is meaningless to a screen reader on its own. The host control owns the accessible name (Notifications, 3 unread), and the badge stays decorative. Only give Count Badge a label when it is standing alone with no control to name it — and then it owns a persistent polite live region, because a live region must exist before the message it announces.

On this page