Notification Triage Panel
依日期或來源分組的通知中心面板,含未讀/全部分頁、群組摺疊,批次清除時項目依序橫掃離場、群組高度以彈簧收合補位。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
<NotificationTriagePanel />
安裝
npx shadcn@latest add https://webberui.com/r/notification-triage-panel.json或在 components.json 設定 registries 後,改用 @webberui/notification-triage-panel 安裝。
安裝依賴後,從 registry JSON(/r/notification-triage-panel.json 的 files[0].content)複製 notification-triage-panel.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge lucide-react使用
import {
NotificationTriagePanel,
type TriageNotification,
} from "@/components/ui/notification-triage-panel";
const notifications: TriageNotification[] = [
{
id: "1",
title: "Aria 提到了你",
description: "在討論串回覆了你的留言。",
source: "Slack",
accent: "violet",
timestamp: Date.now() - 4 * 60_000,
},
{
id: "2",
title: "PR #482 等待你的審查",
source: "GitHub",
accent: "green",
read: true,
timestamp: Date.now() - 42 * 60_000,
},
];
export function Example() {
const [items, setItems] = React.useState(notifications);
return (
<NotificationTriagePanel
notifications={items}
onNotificationsChange={setItems}
groupBy="date"
/>
);
}不傳 notifications 時,改用 defaultNotifications 進入非受控模式,元件會自行管理清除與已讀狀態。
Props
NotificationTriagePanel
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
notifications | TriageNotification[] | — | 受控模式的通知清單,須搭配 onNotificationsChange |
defaultNotifications | TriageNotification[] | [] | 非受控模式的初始通知清單 |
onNotificationsChange | (next: TriageNotification[]) => void | — | 清除或標為已讀時的回呼 |
groupBy | "date" | "source" | "date" | 分組依據 |
tab | "unread" | "all" | — | 受控模式的目前分頁 |
defaultTab | "unread" | "all" | "unread" | 非受控模式的初始分頁 |
onTabChange | (tab: "unread" | "all") => void | — | 分頁切換時的回呼 |
title | React.ReactNode | "通知" | 面板標題 |
relativeTime | boolean | true | 以相對時間顯示,關閉時顯示 HH:MM |
locale | string | — | 時間格式化的地區設定(BCP 47) |
emptyState | React.ReactNode | — | 清單為空時顯示的內容 |
TriageNotification
| 欄位 | 型別 | 說明 |
|---|---|---|
id | string | 穩定唯一識別碼,動畫據此配對前後狀態 |
title | React.ReactNode | 主要標題 |
description | React.ReactNode | 次要說明文字 |
source | string | 來源名稱,groupBy="source" 時作為分組依據 |
icon | React.ReactNode | 左側圖示,預設為鈴鐺 |
timestamp | Date | number | string | 事件時間,groupBy="date" 時作為分組依據 |
read | boolean | 是否已讀 |
accent | "neutral" | "blue" | "green" | "amber" | "red" | "violet" | 圖示底座強調色 |
動畫細節
- 依序橫掃離場:批次清除(整個群組或「清除全部」)時,項目依顯示順序帶 stagger 往右滑出,滑出後高度才以彈簧收合,其下項目隨流補位。
- 群組收合補位:整個群組清空後,群組區塊本身以彈簧收合高度,下方群組自然上移填補;點擊群組標題可摺疊/展開,內容高度同樣以彈簧過渡。
- 單筆處理:點擊項目即標為已讀(未讀分頁中會淡出並收合);hover 或聚焦時顯示右側清除鈕,單筆清除同樣以橫掃離場。
- 調校點:收合彈簧與橫掃時長皆可透過
var(--wb-duration-fast,200ms)等 token 影響過場色彩過渡。
可及性
- 面板為
role="region",分頁列為role="tablist",分頁鈕帶aria-selected並支援←→鍵切換。 - 群組標題鈕帶
aria-expanded與aria-controls,可鍵盤操作摺疊。 - 每筆通知的主體為按鈕(標為已讀),清除鈕獨立且具
aria-label,避免巢狀互動元素。 - 使用者系統開啟「減少動態效果」時,橫掃位移與彈簧改以短暫淡入淡出取代,不影響操作。