{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "notification-center",
  "type": "registry:ui",
  "title": "Notification center",
  "description": "Expands transient notices into a readable, actionable grouped history.",
  "dependencies": [
    "motion"
  ],
  "categories": [
    "overlays-surfaces"
  ],
  "docs": "https://motion-lexicon.pages.dev/en/components/notification-center/",
  "meta": {
    "engines": [
      "motion"
    ],
    "runtimeCost": "light",
    "signature": "Notification stack expands into readable history",
    "sceneFamily": "product-mono",
    "motionRole": "ui",
    "primaryState": "Two recent notifications with unread count",
    "assetProvenance": "self-contained"
  },
  "files": [
    {
      "path": "src/registry/components/notification-center.tsx",
      "type": "registry:ui",
      "target": "components/motion-lexicon/notification-center.tsx",
      "content": "\"use client\";\n\nimport { useId, useState } from \"react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\n\nexport type NotificationCenterItem = { id: string; title: string; detail: string; time: string; unread?: boolean };\nexport type NotificationCenterProps = { items: readonly NotificationCenterItem[]; label?: string; className?: string; onRead?: (id: string) => void };\n\nexport function NotificationCenter({ items, label = \"Notifications\", className = \"\", onRead }: NotificationCenterProps) {\n  const reduced = useReducedMotion() === true; const id = useId(); const [open, setOpen] = useState(false); const [unread, setUnread] = useState(() => new Set(items.filter((item) => item.unread).map((item) => item.id))); const visible = open ? items : items.slice(0, 2);\n  const read = (item: NotificationCenterItem) => { setUnread((current) => { const next = new Set(current); next.delete(item.id); return next; }); onRead?.(item.id); };\n  return <section aria-labelledby={id} className={`rounded-[16px] border border-black/[.1] bg-white p-3 shadow-[0_14px_34px_-27px_rgba(25,25,25,.36)] ${className}`}><div className=\"flex min-h-11 items-center justify-between gap-3\"><div><span className=\"font-mono text-[10px] uppercase tracking-[.15em] text-neutral-500\">Inbox</span><h3 id={id} className=\"mt-0.5 text-[14px] font-medium text-[#292929]\">{label}</h3></div><span className=\"rounded-full bg-[#252827] px-2 py-1 font-mono text-[9px] text-white\">{unread.size}</span></div><ul className=\"mt-2 space-y-1\">{visible.map((item) => <motion.li layout key={item.id}><button type=\"button\" onClick={() => read(item)} className={`flex min-h-11 w-full items-start gap-2 rounded-[10px] p-2 text-left outline-none transition hover:bg-neutral-50 focus-visible:ring-2 focus-visible:ring-[#4568FF] ${unread.has(item.id) ? \"bg-[#f1f3ef]\" : \"\"}`}><span aria-hidden className={`mt-1.5 size-1.5 shrink-0 rounded-full ${unread.has(item.id) ? \"bg-[#4568FF]\" : \"bg-transparent\"}`} /><span className=\"min-w-0 flex-1\"><strong className=\"block text-[11px] text-[#292929]\">{item.title}</strong><span className=\"mt-0.5 block truncate text-[10px] text-neutral-500\">{item.detail}</span></span><time className=\"font-mono text-[9px] text-neutral-400\">{item.time}</time></button></motion.li>)}</ul><AnimatePresence>{items.length > 2 ? <motion.button initial={reduced ? false : { opacity: 0 }} animate={{ opacity: 1 }} type=\"button\" onClick={() => setOpen((value) => !value)} className=\"mt-2 min-h-11 w-full rounded-lg border border-black/[.08] text-[11px] text-neutral-600 outline-none hover:bg-neutral-50 focus-visible:ring-2 focus-visible:ring-[#4568FF]\">{open ? \"Show recent\" : `Show all ${items.length}`}</motion.button> : null}</AnimatePresence></section>;\n}\n"
    }
  ]
}
