Notifications UI
NotificationBell & NotificationCenter components
The portal channel of the Notification service has a ready front-end: a NotificationBell with an unread badge, and a NotificationCenter that lists, paginates and marks notifications as seen. Both are wired to the four generated notification actions, so they render exactly the rows the backend wrote to the notifications table.
They follow the library contract — actions as props, a Zustand store, variants and a theme you can extend. Drop the bell in a top bar and the center in a drawer or page; they coordinate through the same store.
NotificationBell#
A compact unread indicator. It polls the unseen count on an interval and renders a badge; clicking it is yours to handle (usually opening the center).
unseenCountActionNotificationUnseenCountActionOptionalThe GET /notifications/unseen-count action. The bell calls it on mount and every pollInterval to keep the badge live.
pollIntervalnumber (ms)OptionalHow often to refresh the count. Tune for liveness vs. request volume; omit to use the default cadence.
onClick() => voidOptionalFired when the bell is clicked — open the NotificationCenter, navigate, or whatever your shell needs.
NotificationCenter#
The full list. It loads a page of notifications, supports infinite paging, marks items seen individually or all at once, and routes clicks to your handler.
1const a = useApiActions();2 3<NotificationBell4 unseenCountAction={a.NOTIFICATION_UNSEEN_COUNT}5 pollInterval={30000}6 onClick={() => setOpen(true)}7/>;8 9<NotificationCenter10 variant="dropdown"11 listAction={a.NOTIFICATION_LIST}12 unseenCountAction={a.NOTIFICATION_UNSEEN_COUNT}13 markSeenAction={a.NOTIFICATION_MARK_SEEN}14 markAllSeenAction={a.NOTIFICATION_MARK_ALL_SEEN}15 onNotificationClick={(n) =>16 n.entity_name && router.push(`/${n.entity_name}/${n.entity_id}`)17 }18/>;variant'default' | 'compact' | 'dropdown'OptionalRender as a full panel, a dense list, or a dropdown anchored under the bell.
listAction / unseenCountActionactionsOptionallistAction (GET /notifications) pages by { limit, offset, type }; unseenCountAction keeps the header badge in sync. pageSize sets the page length, pollInterval keeps it fresh.
markSeenAction / markAllSeenActionactionsOptionalMark one notification (by notification_id) or every unseen one as read — the store updates optimistically and the badge drops.
onNotificationClick(NotificationItem) => voidOptionalEach item carries type ('verification' | 'system' | 'custom') plus entity_name / entity_id / source, so your handler can deep-link to the record the notification is about — e.g. open the pending verification it announced.
Related sections