An inbox for product events, grouped by day: new notifications rise into Today, and Mark all read collapses every unread dot in turn. Built on Group By List, Badge, Avatar and Button.
When to use
- The bell menu or inbox page of a SaaS product: comments, shares, failed syncs, billing alerts.
- When notifications arrive live and the list must make room without jumping.
When not to use
- A transient confirmation: use Toast.
- An audit trail of who changed what: use a timeline or audit log.
Installation
npx shadcn add @eased-pro/notification-centerNeeds the @eased-pro registry and your Pro token in components.json. Create a token and copy the setup from your account .
Usage
import { NotificationCenter } from "@/components/eased/notification-center/notification-center";<NotificationCenter notifications={items} onNotificationsChange={setItems} onOpen={(n) => router.push(`/inbox/${n.id}`)}/>A notification is a timeline-core TimelineEvent with data: { unread, context? }. Rows with an actor show their avatar; the rest show an icon for their kind (comment, report, alert, billing, member) tinted by tone.
API reference
NotificationCenter
| Prop | Type | Default | Description |
|---|---|---|---|
notifications / defaultNotifications / onNotificationsChange | Notification[] | [] | Newest first. Prepend to add one; it rises in. |
onOpen | (n) => void | A row was opened; it is marked read too. | |
now | number | mount time | For day groups and relative times. |
title | string | "Notifications" | |
icons | Record<kind, ReactNode> | Override the icon per kind. | |
locale | string | "en-US" | |
className | string | "" | Give it a height; the list scrolls with fades. |
Keyboard
| Key | Action |
|---|---|
Tab | Moves to Mark all read, then through the rows. |
Enter / Space | Opens a row and marks it read. |
Accessibility
- Day groups are headings; each row is a button whose text includes its actor, title, context and time.
- The unread count badge is announced as "3 unread"; unread rows say "Unread".
- Mark all read stays focusable when there is nothing to mark, announced as disabled.
Motion
A new notification rises 10px on the snappy spring while the rows under it slide down on smooth and the count rolls. Mark all read shrinks each unread dot top to bottom, 35ms apart (the cascade stays under 320ms). Rows never resize. Reduced motion: rows and dots fade only.
Notes for AI
Use it inside a Popover for a bell menu or full height on an inbox page. Keep the list controlled and prepend new items; keep ids stable.
Don't sort the list yourself into groups or render your own headers: grouping is by day from now. Don't remove read items to show they're read.
Related
- Group By List: the grouped list underneath.
- Badge: the rolling count.