Skip to content

NotificationBell

Terminal window
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/notification-bell.json
See it liveThe bell at zero, at three and past nine; press one to open the panel, mark everything read, or hand over to the whole list.→

A bell that is always lit is a bell nobody reads. So the count is your decision — ordinary edits are recorded and never counted; only what needs a look lights it — and this draws it: nothing at zero, the number past that, 9+ past nine. Pressing it does not leave the screen. The last few entries open under it, and the whole history is one more click.

<NotificationBell
count={unread}
label={t('journal.open')}
title={t('journal.recent')}
markAllLabel={t('journal.markRead')}
onMarkAll={() => markRead.mutate()}
busy={markRead.isPending}
seeAllLabel={t('journal.seeAll')}
onSeeAll={() => navigate('/journal')}
emptyLabel={t('journal.nothingRecent')}
>
<ul>{recent.map((entry) => <RecentLine key={entry.id} entry={entry} />)}</ul>
</NotificationBell>

The rows are yours. A journal entry, a failed upload and a comment are three different lines, and one component cannot draw them; children is the list. What is shared is the frame — the trigger with its badge, the heading with the button that clears the count, the empty line, and the footer that leads to everything.

Mark-all is offered only while there is something to mark. A button that does nothing is worse than no button. It appears when count > 0 and a label is given, and busy holds it while the product is clearing.

See-all closes first, then hands over. The panel is gone before the route changes, so nothing is left open over the page it led to.

Named by what it shows. The bell is called by its label and then by the count on its badge — “Notifications 3” — because someone telling voice control what they see says the number (WCAG 2.5.3). The tooltip is the same words, so a screen reader does not read them twice.

Controlled or not. Leave open out and the bell manages itself; pass it with onOpenChange to drive it — to close it when a row is chosen, say.

Built on Popover and Button, so the panel opens, positions and closes the way every other panel does.

Props

Read from the types in ui/notification-bell.tsx, the file a product copies - so the description of each prop is also what an editor shows over it there.

PropTypeDefault
countrequirednumberHow many things ask to be looked at. Nothing is drawn at zero.
labelrequiredstringWhat the bell is called, for a screen reader and the tooltip.
titlerequiredstringThe heading of the panel.
level1 | 2 | 3 | 4 | 5 | 63Where the panel's heading stands in the outline: 3 by default.
openbooleanOpen, controlled. Left out, the bell manages itself.
onOpenChange(open: boolean) => voidTold when the panel opens or closes, whether the bell is controlled or manages itself.
markAllLabelstringThe button that clears the count, shown only while there is one.
onMarkAll() => voidCalled when the mark-all button is pressed. The button is drawn only with markAllLabel and while count is above zero.
seeAllLabelstringThe footer button, which closes the panel and hands over.
onSeeAll() => voidCalled after the panel closes, when the footer button is pressed. The footer is drawn only with seeAllLabel.
emptyLabelrequiredstringWhat the list says when there are no rows.
childrenReactNodeThe rows.
busybooleanfalseWhile the product is clearing the count: the button waits.
classNamestring

Accessibility

The examples on the stand, through axe 4.14.0 in a browser, in both themes, against WCAG 2.2 A and AA and axe's best practices: 15 rules applied and passed, and none failed. The accessibility report has every item.

History

Each release that changed ui/notification-bell.tsx - the file a product copies - newest first.

  1. v0.41.0
    • docs read every props table from the component's types ee3b159
  2. v0.40.0
    • fix name the notification bell's popup by its title 8c1843e
  3. v0.38.0
    • feat a heading stands at the level the page gives it 101c183
    • fix name the bell by its label and its count a63f636
  4. v0.33.0breaking
    • feat no-raw-button and no-arbitrary-scale ac7a11a
  5. v0.26.0
    • feat add the title-bar bell c0f370a