Notification center

A home for updates with read state, grouped information, and animated disclosure.

Preview
Notification center preview

When to use

  • A bell in the app header with an unread badge and an inbox of recent updates.
  • Notifications people can mark read, expand, and dismiss in bulk.

When not to use

  • Use toast-stack for transient messages that should disappear.
  • Use inbox-triage for a full-page inbox.
  • Use badge for a count without a panel.

shadcn CLI

Also installs (2)

  • manicat-foundation
  • avatar
Manual install(+)
registry.jsonjson
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "notification-center",
  "type": "registry:block",
  "title": "Notification center",
  "description": "A home for updates with read state, grouped information, and animated disclosure.",
  "categories": [
    "blocks"
  ],
  "dependencies": [
    "@radix-ui/react-popover",
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "https://manicat.viraza.net/r/manicat-foundation.json",
    "https://manicat.viraza.net/r/avatar.json"
  ],
  "files": [
    {
      "path": "registry/components/notification-center/notification-center.tsx",
      "type": "registry:component",
      "target": "@components/manicat/notification-center/notification-center.tsx"
    },
    {
      "path": "registry/components/notification-center/notification-center.module.css",
      "type": "registry:component",
      "target": "@components/manicat/notification-center/notification-center.module.css"
    },
    {
      "path": "registry/components/avatar/avatar.tsx",
      "type": "registry:component",
      "target": "@components/manicat/avatar/avatar.tsx"
    },
    {
      "path": "registry/components/avatar/avatar.module.css",
      "type": "registry:component",
      "target": "@components/manicat/avatar/avatar.module.css"
    }
  ],
  "docs": "Docs and live preview: https://uiarc.dev/components/blocks/notification-center",
  "meta": {
    "tier": "free",
    "kind": "block",
    "docs": "https://manicat.viraza.net/components/blocks/notification-center",
    "markdown": "https://uiarc.dev/components/blocks/notification-center/markdown"
  }
}

Usage

Install the component, then copy this into your app. Change the content and the props to fit your screen.

example.tsxtsx
"use client";

import { NotificationCenter } from "@/components/manicat/notification-center/notification-center";
import type { NotificationItem } from "@/components/manicat/notification-center/notification-center";

const notifications: NotificationItem[] = [
  { id: "n1", title: "Elia commented on Accordion", description: "The panel inner should keep its radius.", time: "2m", actor: { name: "Elia Kuratli", photo: "" } },
  { id: "n2", title: "Deploy succeeded", description: "manicat-docs · production", time: "18m", tone: "success" },
  { id: "n3", title: "Usage over 90%", description: "instance i-4332 is near capacity.", time: "1h", tone: "warning" },
];

export function NotificationCenterExample() {
  return <NotificationCenter notifications={notifications} />;
}

Examples

Real screens rather than isolated props. Switch to Code to copy a whole example into your project.

Notification inbox A bell with an unread count, grouped by time, with tones for success and warnings.

Notification inbox A bell with an unread count, grouped by time, with tones for success and warnings. preview

Keyboard interactions

KeysAction
Enter / SpaceOpens the panel from the trigger, toggles a row's details, and activates actions.
EscapeCloses the panel and returns focus to the trigger (Radix Popover).
TabMoves through view toggles, rows, and row actions.

Accessibility

  • The trigger's aria-label includes the unread count; the visual badge is aria-hidden.
  • The summary line is aria-live polite, and outgoing text copies are aria-hidden while they fade.
  • Row toggles use aria-expanded and announce unread state; view toggles use aria-pressed.
  • Focus moves to the next row, or a view toggle, after an item is read, dismissed, or cleared.

Motion

  • The bell tilts when open; counts roll like an odometer in the direction of change.
  • Rows open and collapse their own height on a spring, and bulk actions cascade down the list in under a quarter second.
  • Reduced motion replaces height, roll, and tilt with instant fades.

Responsive behavior

  • The panel is min(424px, 100vw minus 24px) wide and at most min(590px, 100vh minus 24px) tall, with the list scrolling inside.
  • Below 380px padding tightens, the details indent shrinks, and the Mark all read label becomes icon only.
  • Titles and previews ellipsize on one line.

Performance

  • The list is not virtualized and keeps its own copy of the notifications; cap what you pass in.
  • The panel mounts in a portal only while open.

Notes for AI

  • Use in an app header for an inbox of updates. Use toast or toast-stack for transient messages and inbox-triage for a full-page inbox.
  • notifications seeds internal state; sync changes back to your server through onReadChange and onDismiss rather than re-passing the array.