NOTIFICATION CENTRE: "What happened since I last looked" drawer
CLASSES: .notification-centre | .notification-centre-group | .notification-centre-item | .notification-centre-item-unread | .notification-centre-item-icon | .notification-centre-item-body | .notification-centre-item-time | .notification-centre-empty | .notification-centre-footer | .notification-centre-trigger
COMPOSES: Drawer (.drawer shell + drawer_controller.js) | Empty State (.empty-state) | Badge (.badge-dot, .badge-notification)
A right-hand drawer surfacing application status changes, document requests, and event
reminders for parents/applicants — infrequent, often first-time users with no login. Rows are
grouped by day, unread rows carry a surface-tint wash + link-blue dot, and every row is a real
button whose accessible name announces its read state. Requires
notification_centre_controller.js for mark-read / mark-all-read — no fetch, the
host page owns the data.
Default: Two day groups ("Today", "Yesterday"). 3 of 5 rows are unread
(surface-tint wash + link-blue dot before the timestamp). Clicking a row marks it read;
"Mark all as read" clears the rest. The bell's .badge-notification count and
aria-label stay in sync with the live unread count — there is no separate
counter to desync.
<div class="drawer notification-centre"><div class="drawer-body"><h3 class="h6 notification-centre-group">Today</h3><button class="notification-centre-item notification-centre-item-unread">...</button></div></div>
No notifications: Composes .empty-state inside
.notification-centre-empty, which stretches to fill and center in the
remaining drawer height. The footer is omitted entirely — there is nothing to mark as
read — matching the Drawer pattern's own "Without Footer" precedent.
<div class="notification-centre-empty empty-state"><i class="fa-regular fa-bell empty-state-icon"></i><h3 class="empty-state-title">No notifications yet</h3>...</div>
Overflow: 10 unread rows — the bell badge and its aria-label
cap the displayed count at 9+ rather than growing the circle. (Checked
components/badge.css: .badge-notification-ceil is a flush-to-top
position variant, not a numeric-overflow variant — overflow is handled entirely
by capping the badge's text content, the same idiom already shown in the Badge preview's
"99+" example.) Use "Mark all as read" to watch the badge collapse and hide.
<span class="badge badge-danger badge-sm badge-circle badge-notification" data-notification-centre-target="badge">9+</span>
Container: .drawer .notification-centre (composed together on the panel)
Group: .h6 .notification-centre-group (composed together on the day heading)
Row: .notification-centre-item | .notification-centre-item-unread | .notification-centre-item-icon | .notification-centre-item-body | .notification-centre-item-time
Empty: .notification-centre-empty .empty-state (composed together)
Footer: .drawer-footer .notification-centre-footer (composed together)
Trigger: .btn .btn-icon .notification-centre-trigger + .badge .badge-notification
Controller: data-controller="drawer notification-centre" | data-action="click->notification-centre#markRead" | data-action="click->notification-centre#markAllRead"
Events: notification-centre:read { id, unreadCount } | notification-centre:allRead { unreadCount: 0 }