Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Notification Bell Navbar Block for React

An app navbar for a team inbox with a bell whose count follows what you do: the bell opens a panel with All and Unread tabs, rows you can mark read, mark unread or dismiss, and Mark all as read, and a drawer on phones.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

A notification navbar for React with Base UI, for a shared team inbox called Belltide. One bar between the page's rails: the wordmark, four links (Inbox is the current page, marked by a stroke on the bar's bottom edge), a bell and a New thread Shine Button. The bell carries a count chip of what you haven't read and opens a panel over the page with an All and an Unread tab, a row for each notification with its age ("2 min. ago", counting up while the panel is open), a button to mark it read or unread and a button to dismiss it, and Mark all as read. The count on the bell, the two tabs, the line under the title and a polite status all follow what you do. On a phone the same panel opens as a drawer from the bottom, and a menu button opens a sheet from the top with the links and the action. The panel is portalled, so the bar stays 64 pixels (56 on a phone) while it is open. It's built from Popover, Tabs, Badge, Drawer, Sheet, Guides, Shine Button and Button, with your theme's tokens for every colour. For apps and collaboration tools that need an inbox one click from every page.

FAQ

How do I connect it to real notifications?

The notifications are the typed ALERTS array at the top of the file (a title, a detail, a read flag and before, how many minutes before the page loaded it arrived), and the panel works on a copy held in the block's state. Replace the array with your data and call your API from the three handlers in Panel (toggle, dismiss and markAll); the counts, the tabs and the status are all derived from the list, so they stay right. The ages count from the moment the page loaded, so in production give each item its real timestamp and compute the minutes from it. Nothing is typed with a date, so an old demo never goes stale.

How does it work with a keyboard and a screen reader?

The bell is a button named after its count ("Notifications, 3 unread"), says whether the panel is open and which panel it controls, and the count chip itself is hidden from screen readers so it isn't read twice. Enter or Space opens the panel, Escape closes it and puts focus back on the bell. Inside, the tabs are a real tab list; each row is a list item with a heading (its title carries "(unread)" or "(read)" for screen readers), and its two buttons name the notification they act on ("Dismiss: A rule ran on your inbox"). A hidden status line speaks the new count after every change ("2 unread", "No unread notifications"). When a row leaves the list (dismissed, or read while the Unread tab is showing) focus moves to the row that takes its place, or to the empty message, so keyboard users never fall back to the top of the page. Opening the panel moves focus to Mark all as read, the first control inside it. Tab also stops on the open tab's panel, which has a focus ring.

How does it work on a phone?

Below the md breakpoint the nav and New thread leave the bar: it keeps the wordmark, the bell and a menu button, and nothing wraps at 320 pixels. The bell then opens a drawer from the bottom with the same panel (a grabber, the title, both tabs and the rows); swiping it down, Escape or a tap outside closes it and focus returns to the bell. The menu button opens a sheet from the top with the four links (Inbox tinted as the current page) and New thread. Both bells share one state, so a notification dismissed in the drawer is gone from the panel on a desktop too.

Why do the ages say '2 min. ago' and change by themselves?

Each row's age is written by Intl.RelativeTimeFormat ("2 min. ago", "1 hr. ago", "yesterday") and recomputed every 30 seconds while the panel is open; it stops when the panel closes. The catalog's Relative Time Text does the same thing for a page of dates, but it shows the date for a frame before the words, which is visible in a panel that mounts on open, so this block writes the words itself on the first render.

What moves, and what happens with reduced motion?

Nothing moves on load. The panel fades and grows from the bell, the drawer and the sheet slide in, and a band of light sweeps across New thread on hover and keyboard focus. With reduced motion the panel, the drawer and the sheet appear without animating and the light fades in where it stands. The count never animates.

Can I pin the bar or put the bell somewhere else?

Yes. To keep the bar in view add sticky top-0 z-40 bg-background/80 backdrop-blur to the header; the panel still opens under it. The bell and its count are the Count and the two trigger buttons: copy them into any toolbar, with the Panel they open. The panel is 24 rem wide and its list is 18 rem tall, so a long inbox scrolls inside it instead of growing the popup.

  • Pro

    Account Menu Navbar

    Accounts and scopes

    An app bar with an account button behind a split divider that opens a menu: an identity header with plan badge and storage bar, a Switch account radio list, and Profile, Settings, Billing and Sign out.

  • Pro

    Create Menu Navbar

    App toolbars

    An app bar with a Shine Create button that opens a grouped menu with working key hints and a New from template submenu, and a bottom drawer with the same rows on phones.

  • Pro

    A dashboard bar whose page title is a menu of saved views, Pinned and Shared, with a star on the one that opens first, a breadcrumb that follows the choice and a drawer on phones.

  • Pro

    Workspace Switcher Navbar

    Accounts and scopes

    An app bar whose switcher button opens a searchable list of workspaces: recent ones first with number keys, a plan badge on every row, a check on the current one and a Create workspace button in the foot.

  • Pro

    A one-bar marketing navbar for a product roadmap tool: a wordmark, a Product menu of four areas with icons and one-line descriptions, plain links with the current page marked, Sign in and a Shine Button, and a sheet with the same links on phones.

  • Pro

    An unread-messages bar for a team messaging app: a dot, a rolling count, a link to the inbox and a Mark all read button that rolls the count to zero.