KQ-1308 · NOTICE/CENTER

Notice Center

A notification center whose groups stack into a deck: pressing one deals it out, each hidden row starting where its layer was and gliding down to its place on glide in a cascade while the group's measured height glides open, and Show less gathers them back on the exit ease. A row or a whole stack follows a sideways swipe 1:1, is thrown off on the exit ease when its projected rest passes 40% of its width (or snaps back on snap with the release velocity), and the rows under it close the gap on glide. Mark all read sends a band down the list that clears each unread row as it passes — the dot shrinks on flick — the tab pill slides on snap and times roll as `now` moves; arrows walk the rows, Enter opens, Right deals and Left gathers a stack, Delete dismisses.

KQ-1308 · NOTICE/CENTER

Notifications7 unread

  • Fieldline Builds · 4

  • Fernworks Docs · 2

  • Gaugeworks Monitor · 2

  • Waylight Pay · 2

  • Coldbrook Bank · 2

7 unread · 12 notices

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/notice-center

Props

notices / defaultNotices
Notice[]
default defaultNotices
Every notice: its source, title, body, time, read state and whether it mentions you. Controlled or uncontrolled.
onNoticesChange
(notices: Notice[]) => void
default —
Fires from the dismiss, open or sweep that changed the list, with the whole new list.
sources
NoticeSource[]
default defaultNoticeSources
Where notices come from: a name, an icon and a colour for each.
now
Date | number
default defaultNoticeNow
The moment every notice is dated against. Move it and the times roll over; days are UTC days.
filter / defaultFilter
"all" | "unread" | "mentions"
default "all"
The selected tab. Controlled or uncontrolled.
onFilterChange
(filter: NoticeFilter) => void
default —
Fires when a tab is chosen by press or arrow key.
selected / defaultSelected
string | null
default null
The open notice, shown in the detail pane from 600px wide. Controlled or uncontrolled.
onSelectedChange
(id: string | null) => void
default —
Fires when opening or dismissing changes the open notice.
onOpen
(id: string) => void
default —
A notice was opened by press or Enter. It is marked read first.
onDismiss
(ids: string[]) => void
default —
Notices were dismissed by swipe, key or button: one, or a whole collapsed group.
onMarkAllRead
(ids: string[]) => void
default —
Mark all read cleared these notices.
onReadChange
(id: string, read: boolean) => void
default —
One notice was marked read or unread.
onRetry
() => void
default —
The Retry button of the error state.
stack
"deck" | "fan" | "flat"
default "deck"
How a collapsed group shows what is under its newest notice: layers peeking below, the same layers fanned, or a flat “+3”.
sweep
number
default 480
How long Mark all read's band takes to cross the list, in ms.
group
"source" | "day" | "off"
default "source"
Group by source into collapsible stacks, by day under sticky Today, Yesterday and Earlier headings, or not at all.
title
string
default "Notifications"
The panel's heading and accessible name.
status
"ready" | "loading" | "error"
default "ready"
Loading draws placeholder rows; error offers Retry.
label
string
default —
The region's accessible name, when it should differ from the title.
sound
boolean
default false
Play a swish on dismiss and Mark all read and a pop on dealing, gathering and read changes. Off unless asked for.
disabled
boolean
default false
Shows the notices but takes no presses, swipes or keys.
className
string
default —
Classes for the root. The root is h-[560px] by default; pass a height to change it.