X-09 · Composites · App components
All elements · NotificationCenter on the Composites page
Last checked 2026-10-22 · Awaiting approval · Accessibility tests
Approve NotificationCenter
Approving as
Bell with unread badge; a Popover holding a grouped, sectioned List. The bell in the app shell above opens the same popover.
The specimen below is copied from
notifications.html, which
shows it inside the app shell, by bun scripts/design-pages/build-composite-pages.mjs — edit
that file, not this one; --check fails when they drift.
| Axis | Values |
|---|---|
.qf-bell · __badge |
trigger and unread count |
.qf-notifications · .qf-list__item[data-unread] · __time
|
panel parts |
- Today
- jdJane Doe assigned you a taskApprove invoice INV-2026-0412 · due tomorrow2h
- Batch #2041 finished indexing14 pages · 0 errors4h
- Yesterday
- 3 tasks are overdueIn the Finance queue1d
- Alex Kim mentioned you"…can @Jane confirm the amount?"1d
- jdJane Doe assigned you a taskApprove invoice INV-2026-04122h
- Batch #2041 finished indexing14 pages · 0 errors4h
Guidance
When to use
- Use it in the app bar to collect events addressed to the user, such as task assignments, mentions and finished batch jobs.
- Use it when users check events on their own schedule rather than being interrupted.
- Use the unread badge on the bell to show that new items are waiting.
- Use the grouped list (Today, Yesterday) when users scan recent events by time.
When to consider something else
- Use a Toast for immediate, short-lived feedback about an action the user just took. See Toast.
- Use a Banner for a condition that affects the whole page and needs attention now. See Banner.
- Use the Inbox for tasks the user must work, not just read about. See Inbox.
- Use a plain Popover when the panel holds anything other than an event list. See Popover.
Usability
-
Write each item as who did what, with the object in the secondary line:
Jane Doe assigned you a task,Approve invoice INV-2026-0412 · due tomorrow. - Mark unread items with
data-unreadand keep Mark all read in the header. -
Show relative time in
.qf-notifications__time, with the full date available on focus or hover. - Make each item open the object or task it refers to.
- End the panel with View all notifications for history beyond the popover.
- Do not show unread state only by tint or dot color.
- Do not use the notification center for errors the user must act on now.
- Do not leave the badge showing after every item has been read.
Accessibility
Keyboard
| Keys | Action |
|---|---|
| Enter or Space | On the bell, opens the notifications popover. |
| Tab | Moves through Mark all read, each notification item and View all notifications. |
| Enter | On an item, opens what it refers to and marks it read. |
| Escape | Closes the popover and returns focus to the bell. |
Roles and names
-
The bell is an icon-only button; its name must include the unread count, for example
Notifications, 3 unread, and it carriesaria-expandedandaria-controls. -
The badge (
.qf-bell__badge) is visual; hide it witharia-hiddenonce the count is in the bell's name. -
The panel is a
.qf-popover; the binding should label itNotificationswitharia-labelledbyon its header. -
Items are
.qf-list__itemrows in a<ul>; group headers are.qf-list__headeritems. Interactive rows (data-interactive) must be real buttons or links, not bare<li>elements. -
Unread state must be in the accessible name or description, for example a visually hidden
Unread.
Focus
- Opening the popover moves focus to its first control or first item.
- Closing with Escape or by choosing an item returns focus to the bell, unless the item opened a window.
- Mark all read keeps focus on the button and updates the count.
Other requirements
- Announce new notifications that arrive while the user works through a polite live region, without moving focus (4.1.3).
- The badge text is 0.625rem bold on the error color; confirm 4.5:1 contrast and that it stays readable at 200% zoom (1.4.3, 1.4.4).
- Avatars use initials or icons; the item text, not the avatar, must carry who acted (1.1.1).
- Item rows and the header buttons must meet 24 by 24 CSS pixels (2.5.8).
Test your implementation too. This guidance covers the element as specified here. How a screen composes it (labels, order, announcements) still needs its own keyboard and screen reader check.
Accessibility tests
Passed the gate (run 358b316 on 2026-10-22): no finding in any theme. Awaiting a person’s approval of the checklist below.
| Area | Automated | A person checks |
|---|---|---|
| General | Passed | Color is never the only cue, text alternatives say the same thing as the graphic, and the element reads the same in the light and the dark theme. |
| Zoom | Passed | At 200% zoom, at 320 CSS pixels wide and with the WCAG text-spacing overrides, nothing is lost, clipped or overlapping. |
| Keyboard | Passed | Every row of the Keyboard table works, focus is always visible and never trapped, and the tab order follows the reading order. (4 rows) |
| Screen reader | Passed | With NVDA or JAWS on Windows and VoiceOver on macOS, names, roles and states are announced as Roles and names says, and changes are announced once. (5 items) |
Approving. When the checklist passes on the checked run, record it with
bun run a11y:approve -- notifications --by "Your name" and commit
a11y/approvals.json with the rebuilt pages.
All test status
Package
Consumers link one stylesheet, css/classic/index.css, which includes every element. The
files below are where this element is defined.
Latest updates
No recorded changes yet.