{ "$schema": "https://blode.co/ui/schema/registry-item.json", "name": "bubble", "title": "Bubble", "author": "Matthew Blode", "description": "A message surface for chat interfaces, with variants, alignment, reactions, and composable content.", "dependencies": ["@base-ui/react"], "files": [ { "path": "ui/bubble.tsx", "content": "import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { cva } from \"class-variance-authority\";\nimport type { VariantProps } from \"class-variance-authority\";\nimport type * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst BubbleGroup = ({ className, ...props }: React.ComponentProps<\"div\">) => (\n \n);\n\nconst bubbleVariants = cva(\n \"group/bubble relative flex w-fit min-w-0 max-w-[80%] flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full\",\n {\n defaultVariants: {\n variant: \"default\",\n },\n variants: {\n variant: {\n default:\n \"*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80\",\n destructive:\n \"*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30\",\n ghost:\n \"border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50\",\n muted:\n \"*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]\",\n outline:\n \"*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30\",\n secondary:\n \"*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]\",\n tinted:\n \"*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]\",\n },\n },\n },\n);\n\nconst Bubble = ({\n variant = \"default\",\n align = \"start\",\n className,\n ...props\n}: React.ComponentProps<\"div\"> &\n VariantProps & {\n align?: \"start\" | \"end\";\n }) => (\n \n);\n\nconst BubbleContent = ({ className, render, ...props }: useRender.ComponentProps<\"div\">) =>\n useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(\n {\n className: cn(\n \"w-fit min-w-0 max-w-full overflow-hidden wrap-break-word rounded-3xl border border-transparent px-3 py-2.5 text-sm leading-relaxed group-data-[align=end]/bubble:self-end [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/30 [button]:text-left\",\n className,\n ),\n },\n props,\n ),\n render,\n state: {\n slot: \"bubble-content\",\n },\n });\n\nconst bubbleReactionsVariants = cva(\n \"absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0\",\n {\n defaultVariants: {\n align: \"end\",\n side: \"bottom\",\n },\n variants: {\n align: {\n end: \"right-3\",\n start: \"left-3\",\n },\n side: {\n bottom: \"bottom-0 translate-y-3/4\",\n top: \"-translate-y-3/4 top-0\",\n },\n },\n },\n);\n\nconst BubbleReactions = ({\n side = \"bottom\",\n align = \"end\",\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n align?: \"start\" | \"end\";\n side?: \"top\" | \"bottom\";\n}) => (\n \n);\n\nexport { BubbleGroup, Bubble, BubbleContent, BubbleReactions };\n", "type": "registry:ui", "target": "" } ], "type": "registry:ui" }