{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "quack-bubble",
"title": "Quack Bubble",
"description": "A message that has a voice. The assistant's bubble carries the mark and a squared corner on the side it speaks from; the user's is plain lime vinyl. The mark is a prop, so the assistant can be anyone.",
"registryDependencies": [
"@duck/theme",
"@duck/duck-mark"
],
"files": [
{
"path": "registry/duck/ui/quack-bubble.tsx",
"content": "import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { DuckMark } from \"@/components/ui/duck-mark\";\n\n/**\n * QuackBubble — a message that has a voice, which is the first time in this\n * registry that the Quack prefix has been literally true.\n *\n * The assistant speaks from the pond side: its bubble carries the mark and a\n * squared corner on the side it speaks from — the corner the die did not round\n * off. No CSS triangle tail: a tail drawn with borders cannot survive a 3px\n * sticker edge, and a clip-path notch would cut the edge open.\n *\n * The user's bubble is plain lime vinyl with no mark. One voice in the\n * conversation is a character; the other is a person.\n *\n * Which character is the consumer's business, so the mark is a prop and the\n * duck is only its default. A transcript is the last place a design system\n * should insist on its own mascot.\n */\nexport interface QuackBubbleProps extends React.ComponentProps<\"div\"> {\n from?: \"assistant\" | \"user\";\n /** Timestamp, model name, \"edited\" — whatever belongs under the message. */\n meta?: string;\n /**\n * The assistant's face, inside a 2rem well that is already aria-hidden.\n * Rendered as given, so a replacement sizes itself — the mascot is 1.25rem.\n */\n mark?: React.ReactNode;\n}\n\nfunction QuackBubble({\n className,\n from = \"assistant\",\n meta,\n mark =