Yugen UI

NotificationCenter

NotificationCenter is a bell with an unread count. It opens a panel of notifications grouped by day: a Popover on desktop, a bottom sheet on mobile.

Each notification has an avatar or an intent icon, a title, body, relative time, an unread dot (with hidden text) and Mark as read / Dismiss actions. The panel has All / Unread filters, Mark all as read, and empty (Empty), loading (SkeletonList through useSpinDelay) and error (ErrorState with Retry) states. Times are computed after mount or from the now prop, so hydration doesn't mismatch. New notifications are announced politely through useAnnounce. useNotifications() is a small store for demos.
Yugen Labs · experimentalThis component is outside SemVer: its API can change in a minor release, and What's new says so. Versioning policy

Import

Install from npm, copy the source into your project with @yugen-ui/cli or the shadcn CLI, or import directly when working in this repo.

TSX
// npm install yugen-uiimport { NotificationCenter, useNotifications, type NotificationItem } from "yugen-ui";

Variants

Each tile is a standalone example: hover to copy, or press Code to see the source.

Loading & error

The skeleton only shows when the wait is longer than 300ms; the error state has a Retry button when onRetry is passed.

Usage

Do
  • Write titles that say who did what; put the details in body.
  • Make a notification clickable so it leads to the right place and marks itself as read.
  • Use the warning / error intents only for things people need to act on.
Don't
  • Don't use NotificationCenter for immediate feedback on an action. Use Toast.
  • Don't count read notifications on the bell.
  • Don't compute the current time during server render. Pass now, or let the component read it after mount.

Props

Prop · TypeDefaultDescription
itemsNotificationItem[]Default: —{ id, title, body?, time, read?, author?, icon?, intent?, href? }.
onMarkRead / onMarkAllRead / onDismiss(id) => void / () => void / (id) => voidDefault: —Actions (controlled).
onItemClick(item) => voidDefault: —Click on a notification; also calls onMarkRead if it is unread.
loading / error / onRetryboolean / ReactNode / () => voidDefault: —Loading and error states.
nowDate | numberDefault: —Fixed reference time (SSR, tests).
open / defaultOpen / onOpenChangebooleanDefault: —Panel open state.
mode / breakpoint"auto" | "popover" | "sheet" / "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | numberDefault: "auto" / "3xl"Popover or bottom sheet; breakpoint takes the same tokens as Sheet (a px number is deprecated, removed in 1.0).
title / footer / announcestring / ReactNode / booleanDefault: "Notifications" / — / trueTitle, panel footer, announcing new notifications.
useNotifications(initial){ items, unreadCount, add, markRead, markAllRead, dismiss, clear, bind }Default: —Small store for demos; spread bind into NotificationCenter.

Messages

Text built into the component: labels, aria-labels, screen reader announcements.

English by default. Change it with the messages prop of YugenProvider, by the namespace below; messagesVi has the Vietnamese set. See Interface language.

messages.notificationCenter

Key · TypeDefault (English)messagesVi
titlestring

Tiêu đề bảng, tên nút chuông và tên danh sách (khi không truyền title).

Default (English)"Notifications"messagesVi"Thông báo"
triggerUnread(title: string, unread: number) => string

Tên nút chuông khi còn thông báo chưa đọc.

Default (English)(title, unread) => `${title}, ${unread} unread`messagesVi(title, unread) => `${title}, ${unread} chưa đọc`
closestring

Nhãn nút đóng bottom sheet.

Default (English)"Close"messagesVi"Đóng"
markAllReadstringDefault (English)"Mark all as read"messagesVi"Đánh dấu tất cả đã đọc"
filterstring

Tên nhóm tab lọc.

Default (English)"Filter notifications"messagesVi"Lọc thông báo"
allstringDefault (English)"All"messagesVi"Tất cả"
unreadstring

Tab "chưa đọc" (số lượng được nối thêm phía sau).

Default (English)"Unread"messagesVi"Chưa đọc"
loadErrorstring

Tiêu đề ErrorState khi tải lỗi.

Default (English)"Couldn't load notifications"messagesVi"Không tải được thông báo"
emptyTitlestringDefault (English)"No notifications yet"messagesVi"Chưa có thông báo"
emptyDescriptionstringDefault (English)"New notifications will appear here."messagesVi"Thông báo mới sẽ xuất hiện ở đây."
emptyUnreadTitlestringDefault (English)"You're all caught up"messagesVi"Bạn đã đọc hết"
emptyUnreadDescriptionstringDefault (English)"No unread notifications."messagesVi"Không còn thông báo chưa đọc."
unreadSuffixstring

Chữ ẩn nối sau tiêu đề mục chưa đọc, cho trình đọc màn hình.

Default (English)", unread"messagesVi", chưa đọc"
markReadstring

Tooltip nút đánh dấu đã đọc.

Default (English)"Mark as read"messagesVi"Đánh dấu đã đọc"
markReadItem(title: string) => string

Tên nút đánh dấu đã đọc của một mục.

Default (English)(title) => `Mark as read: ${title}`messagesVi(title) => `Đánh dấu đã đọc: ${title}`
dismissstring

Tooltip nút bỏ thông báo.

Default (English)"Dismiss"messagesVi"Bỏ thông báo"
dismissItem(title: string) => string

Tên nút bỏ thông báo của một mục.

Default (English)(title) => `Dismiss: ${title}`messagesVi(title) => `Bỏ thông báo: ${title}`
announceOne(title: string) => string

Đọc qua live region khi có một thông báo mới.

Default (English)(title) => `New notification: ${title}`messagesVi(title) => `Thông báo mới: ${title}`
announceMany(count: number) => string

Đọc qua live region khi có nhiều thông báo mới.

Default (English)(count) => (count === 1 ? "1 new notification" : `${count} new notifications`)messagesVi(count) => `${count} thông báo mới`
justNowstringDefault (English)"Just now"messagesVi"Vừa xong"
minutesAgo(minutes: number) => stringDefault (English)(minutes) => (minutes === 1 ? "1 minute ago" : `${minutes} minutes ago`)messagesVi(minutes) => `${minutes} phút trước`
hoursAgo(hours: number) => stringDefault (English)(hours) => (hours === 1 ? "1 hour ago" : `${hours} hours ago`)messagesVi(hours) => `${hours} giờ trước`
todaystringDefault (English)"Today"messagesVi"Hôm nay"
yesterdaystringDefault (English)"Yesterday"messagesVi"Hôm qua"