{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "message-bubble",
  "type": "registry:ui",
  "title": "iOS Message Bubbles",
  "description": "Beautiful iOS-style message bubbles with authentic iMessage appearance, message grouping, and tail effects.",
  "dependencies": [],
  "files": [
    {
      "path": "registry/new-york/ui/message-bubble.tsx",
      "content": "\"use client\";\n\nimport \"./message-bubble.css\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport interface MessageBubbleProps {\n\tmessage: string;\n\tvariant?: \"sent\" | \"received\";\n\tgrouped?: \"first\" | \"middle\" | \"last\" | \"none\";\n\tclassName?: string;\n\tchildren?: React.ReactNode;\n}\n\nexport function MessageBubble({\n\tmessage,\n\tvariant = \"received\",\n\tgrouped = \"none\",\n\tclassName,\n\tchildren,\n}: MessageBubbleProps) {\n\tconst groupedClasses =\n\t\tgrouped === \"first\"\n\t\t\t? \"imessage-grouped-first mb-1.5\"\n\t\t\t: grouped === \"last\"\n\t\t\t\t? \"imessage-grouped-last\"\n\t\t\t\t: grouped === \"middle\"\n\t\t\t\t\t? \"imessage-grouped-middle mb-1.5\"\n\t\t\t\t\t: \"\";\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t\"imessage-bubble\",\n\t\t\t\tvariant === \"sent\" ? \"imessage-from-me\" : \"imessage-from-them\",\n\t\t\t\tgroupedClasses,\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{children || <p className=\"whitespace-pre-wrap\">{message}</p>}\n\t\t</div>\n\t);\n}\n\nexport interface ChatMessageProps {\n\ttimestamp?: string;\n\tmessages: string[];\n\tvariant?: \"sent\" | \"received\";\n\tclassName?: string;\n\tshowTimestamp?: boolean;\n}\n\nexport function ChatMessage({\n\ttimestamp,\n\tmessages,\n\tvariant = \"received\",\n\tclassName,\n\tshowTimestamp = true,\n}: ChatMessageProps) {\n\tconst hasMultipleMessages = messages.length > 1;\n\n\tconst getGroupedType = (index: number, total: number) => {\n\t\tif (total === 1) return \"none\";\n\t\tif (index === 0) return \"first\";\n\t\tif (index === total - 1) return \"last\";\n\t\treturn \"middle\";\n\t};\n\n\treturn (\n\t\t<div className={cn(\"flex w-full flex-col\", className)}>\n\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t{messages.map((message, index) => (\n\t\t\t\t\t<MessageBubble\n\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\tmessage={message}\n\t\t\t\t\t\tvariant={variant}\n\t\t\t\t\t\tgrouped={\n\t\t\t\t\t\t\thasMultipleMessages\n\t\t\t\t\t\t\t\t? getGroupedType(index, messages.length)\n\t\t\t\t\t\t\t\t: \"none\"\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</div>\n\n\t\t\t{showTimestamp && timestamp && (\n\t\t\t\t<span\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"mt-1 px-2 text-xs text-muted-foreground\",\n\t\t\t\t\t\tvariant === \"sent\" && \"text-right\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{timestamp}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/new-york/ui/message-bubble.css",
      "content": "/* iOS-style message bubbles */\n.imessage-bubble {\n\tword-wrap: break-word;\n\tline-height: 24px;\n\tposition: relative;\n\tpadding: 8px 20px;\n\tmax-width: 60vw;\n\tborder-radius: 20px;\n}\n\n.imessage-bubble::before,\n.imessage-bubble::after {\n\tcontent: \"\";\n\tposition: absolute;\n\tbottom: 0;\n\theight: 18px;\n}\n\n/* Grouped messages have tighter corner radii on the stacking side */\n/* Received messages (left side) - tight corners on left side */\n.imessage-grouped-first.imessage-from-them {\n\t/* biome-ignore lint/complexity/noImportantStyles: need to override radius */\n\tborder-radius: 20px 20px 20px 5px !important;\n}\n\n.imessage-grouped-middle.imessage-from-them {\n\t/* biome-ignore lint/complexity/noImportantStyles: need to override radius */\n\tborder-radius: 5px 20px 20px 5px !important;\n}\n\n.imessage-grouped-last.imessage-from-them {\n\t/* biome-ignore lint/complexity/noImportantStyles: need to override radius */\n\tborder-radius: 5px 20px 20px 20px !important;\n}\n\n.imessage-grouped-last.imessage-from-them {\n\t/* biome-ignore lint/complexity/noImportantStyles: need to override radius */\n\tborder-radius: 5px 20px 20px 20px !important;\n}\n\n/* Sent messages (right side) - tight corners on right side */\n.imessage-grouped-first.imessage-from-me {\n\t/* biome-ignore lint/complexity/noImportantStyles: need to override radius */\n\tborder-radius: 20px 20px 5px 20px !important;\n}\n\n.imessage-grouped-middle.imessage-from-me {\n\t/* biome-ignore lint/complexity/noImportantStyles: need to override radius */\n\tborder-radius: 20px 5px 5px 20px !important;\n}\n\n.imessage-grouped-last.imessage-from-me {\n\t/* biome-ignore lint/complexity/noImportantStyles: need to override radius */\n\tborder-radius: 20px 5px 20px 20px !important;\n}\n\n/* Bot messages (from-them style) */\n.imessage-from-them {\n\tbackground-color: var(--color-zinc-300);\n\tcolor: black;\n\talign-self: flex-start;\n}\n\n.imessage-from-them::before {\n\tleft: -7px;\n\twidth: 20px;\n\tbackground-color: var(--color-zinc-300);\n\tborder-bottom-right-radius: 16px;\n}\n\n.imessage-from-them::after {\n\tleft: -26px;\n\twidth: 26px;\n\tbackground-color: var(--color-background);\n\tborder-bottom-right-radius: 10px;\n}\n\n/* User messages (from-me style) */\n.imessage-from-me {\n\tcolor: black;\n\tbackground: #00bbff;\n\talign-self: flex-end;\n}\n\n.imessage-from-me::before {\n\tright: -7px;\n\twidth: 20px;\n\tbackground-color: #00bbff;\n\tborder-bottom-left-radius: 16px 14px;\n}\n\n.imessage-from-me::after {\n\tright: -26px;\n\twidth: 26px;\n\tbackground-color: var(--color-background);\n\tborder-bottom-left-radius: 10px;\n}\n\n/* Grouped iMessage bubbles for NEW_MESSAGE_BREAK */\n/* Hide tails for grouped messages except the last one */\n.imessage-grouped-first::before,\n.imessage-grouped-first::after,\n.imessage-grouped-middle::before,\n.imessage-grouped-middle::after {\n\tdisplay: none;\n}\n",
      "type": "registry:ui"
    }
  ]
}