{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "notification",
  "title": "Notification",
  "description": "The persistent inbox row: unread edge bar and tint, leading avatar or severity tile with an optional type-badge overlay, two-line title and preview, right-hand time column, inline decision row and a hover-revealed quick-action pill.",
  "dependencies": [
    "@untitledui/icons@^0.0.22"
  ],
  "registryDependencies": [
    "@nx-ui/utils"
  ],
  "files": [
    {
      "path": "components/ui/notification.tsx",
      "content": "import * as React from \"react\"\nimport { AlertCircle, CheckCircle, InfoCircle } from \"@untitledui/icons\"\n\nimport { cn } from \"@/lib/utils\"\n\n/**\n * Notification — the persistent inbox row, modelled on the production nexus4\n * notification centre anatomy. A row is, left to right:\n *\n *   - `NotificationDot` — the \"new\" accent: a thin edge bar hugging the left\n *     edge of the row (render it only while the item is unread/unseen).\n *   - `NotificationLeading` — the icon slot: an avatar, an image, or a\n *     `NotificationIcon` severity tile, optionally overlaid with a\n *     `NotificationBadge` mini-tile (Slack-style avatar + type combo).\n *   - `NotificationBody` — `NotificationTitle` (bold while the row is unread),\n *     optional `NotificationDescription` preview, optional `NotificationLabel`\n *     context line (e.g. an organisation name), optional `NotificationActions`\n *     inline decision row (Accept / Decline).\n *   - `NotificationTime` — the right-hand meta column (relative time stacked\n *     over an absolute `<time>`), which fades out under the quick-action pill.\n *   - `NotificationQuickActions` — a hover/focus-revealed pill of\n *     `NotificationQuickAction` icon buttons (view, read-toggle,\n *     archive-toggle, delete).\n *\n * Unread state lives on the root (`unread` prop → tinted background +\n * `data-unread`, which the title reads for its bold weight). This is the\n * persistent counterpart to `sonner` toasts — compose rows inside the\n * `notification-centre` block's popover, or standalone in an activity feed.\n *\n * @example\n * <Notification unread>\n *   <NotificationDot />\n *   <NotificationLeading><Avatar>…</Avatar></NotificationLeading>\n *   <NotificationBody>\n *     <NotificationTitle>Ada mentioned you</NotificationTitle>\n *     <NotificationDescription>“can you review batch #0412?”</NotificationDescription>\n *   </NotificationBody>\n *   <NotificationTime>5m ago</NotificationTime>\n *   <NotificationQuickActions>\n *     <NotificationQuickAction aria-label=\"Mark as read\"><Check /></NotificationQuickAction>\n *   </NotificationQuickActions>\n * </Notification>\n */\n\nfunction Notification({\n  className,\n  unread = false,\n  ...props\n}: React.ComponentProps<\"div\"> & { unread?: boolean }) {\n  return (\n    <div\n      data-slot=\"notification\"\n      data-unread={unread ? \"\" : undefined}\n      className={cn(\n        \"group/notification relative flex gap-3 px-4 py-3 text-sm transition-colors hover:bg-muted/50\",\n        unread && \"bg-brand-50/50 dark:bg-brand-950/20\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\n/**\n * The \"new\" accent — a thin bar hugging the row's left edge, in the alert\n * red the nexus4 inbox uses for not-yet-seen items. Render conditionally.\n */\nfunction NotificationDot({\n  className,\n  ...props\n}: React.ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"notification-dot\"\n      aria-hidden=\"true\"\n      className={cn(\n        \"absolute inset-y-0.5 left-0 w-0.5 rounded-r-full bg-fg-error-primary\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction NotificationLeading({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"notification-leading\"\n      className={cn(\"relative shrink-0 pt-1\", className)}\n      {...props}\n    />\n  )\n}\n\ntype NotificationSeverity = \"info\" | \"success\" | \"warning\" | \"critical\"\n\nconst severityStyles: Record<NotificationSeverity, string> = {\n  info: \"bg-utility-blue-50 text-utility-blue-600\",\n  success: \"bg-utility-green-50 text-utility-green-600\",\n  warning: \"bg-utility-yellow-50 text-utility-yellow-600\",\n  critical: \"bg-utility-red-50 text-utility-red-600\",\n}\n\nconst severityGlyphs: Record<\n  NotificationSeverity,\n  React.ComponentType<{ className?: string }>\n> = {\n  info: InfoCircle,\n  success: CheckCircle,\n  warning: AlertCircle,\n  critical: AlertCircle,\n}\n\n/**\n * The severity tile — a size-9 tinted circle for system notifications with no\n * avatar. Pass a glyph as children, or omit to get the severity's default.\n */\nfunction NotificationIcon({\n  className,\n  severity = \"info\",\n  children,\n  ...props\n}: React.ComponentProps<\"div\"> & { severity?: NotificationSeverity }) {\n  const Glyph = severityGlyphs[severity]\n  return (\n    <div\n      data-slot=\"notification-icon\"\n      data-severity={severity}\n      className={cn(\n        \"flex size-9 shrink-0 items-center justify-center rounded-full [&_svg]:size-4 [&_svg]:shrink-0\",\n        severityStyles[severity],\n        className\n      )}\n      {...props}\n    >\n      {children ?? <Glyph />}\n    </div>\n  )\n}\n\n/**\n * A mini severity tile overlaid on the bottom-right corner of the leading\n * avatar/image (place inside `NotificationLeading`, after the avatar).\n */\nfunction NotificationBadge({\n  className,\n  severity = \"info\",\n  children,\n  ...props\n}: React.ComponentProps<\"span\"> & { severity?: NotificationSeverity }) {\n  const Glyph = severityGlyphs[severity]\n  return (\n    <span\n      data-slot=\"notification-badge\"\n      data-severity={severity}\n      className={cn(\n        \"absolute -right-1.5 -bottom-1 z-10 flex size-5 items-center justify-center rounded-full border-2 border-background [&_svg]:size-2.5 [&_svg]:shrink-0\",\n        severityStyles[severity],\n        className\n      )}\n      {...props}\n    >\n      {children ?? <Glyph />}\n    </span>\n  )\n}\n\nfunction NotificationBody({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"notification-body\"\n      className={cn(\"flex min-w-0 flex-1 flex-col justify-center\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction NotificationTitle({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"notification-title\"\n      className={cn(\n        \"line-clamp-2 text-[13px] leading-snug font-medium text-foreground/80 group-data-unread/notification:font-semibold group-data-unread/notification:text-foreground\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction NotificationDescription({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"notification-description\"\n      className={cn(\n        \"mt-0.5 line-clamp-2 text-xs leading-relaxed text-muted-foreground/80\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\n/** A one-line context label (e.g. organisation name) under the description. */\nfunction NotificationLabel({\n  className,\n  ...props\n}: React.ComponentProps<\"span\">) {\n  return (\n    <span\n      data-slot=\"notification-label\"\n      className={cn(\n        \"mt-1 block truncate text-[10px] leading-tight font-medium text-brand-600 dark:text-brand-400\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\n/**\n * The right-hand meta column — relative time stacked over an absolute\n * timestamp. When the row carries a quick-actions pill it fades out on\n * hover/focus so the pill never overlaps the text.\n */\nfunction NotificationTime({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"notification-time\"\n      className={cn(\n        \"flex shrink-0 flex-col items-end gap-0.5 pt-0.5 text-[10px] leading-tight tabular-nums text-muted-foreground/60\",\n        \"transition-opacity duration-150 group-has-data-[slot=notification-quick-actions]/notification:group-hover/notification:opacity-0 group-has-data-[slot=notification-quick-actions]/notification:group-focus-within/notification:opacity-0\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\n/** An inline decision row (Accept / Decline) inside the body. */\nfunction NotificationActions({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"notification-actions\"\n      className={cn(\"mt-2 flex items-center gap-2\", className)}\n      {...props}\n    />\n  )\n}\n\n/**\n * The hover/focus-revealed quick-actions pill, floated over the top-right\n * corner of the row. Keyboard users get it via focus-within.\n */\nfunction NotificationQuickActions({\n  className,\n  ...props\n}: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"notification-quick-actions\"\n      className={cn(\n        \"absolute top-2.5 right-2.5 z-10 flex items-center gap-1 rounded-full border border-border/60 bg-popover/95 px-2 py-1 opacity-0 shadow-sm backdrop-blur-sm transition-opacity group-hover/notification:opacity-100 group-focus-within/notification:opacity-100\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction NotificationQuickAction({\n  className,\n  destructive = false,\n  ...props\n}: React.ComponentProps<\"button\"> & { destructive?: boolean }) {\n  return (\n    <button\n      type=\"button\"\n      data-slot=\"notification-quick-action\"\n      className={cn(\n        \"rounded-md p-1 text-muted-foreground/60 transition-colors outline-none hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring/50 [&_svg]:size-3.5 [&_svg]:shrink-0\",\n        destructive ? \"hover:text-destructive\" : \"hover:text-foreground\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Notification,\n  NotificationLeading,\n  NotificationIcon,\n  NotificationBadge,\n  NotificationBody,\n  NotificationTitle,\n  NotificationDescription,\n  NotificationLabel,\n  NotificationTime,\n  NotificationActions,\n  NotificationQuickActions,\n  NotificationQuickAction,\n  NotificationDot,\n}\nexport type { NotificationSeverity }\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}