Chat Message
fluid-functionalism/chat-messageFreeComponent
A single chat transcript entry with baked-in entrance and layout motion. Right-aligned accent bubble for the user, left-aligned muted bubble for the assistant, with optional file attachments. Adapts to the global shape setting.
Install it
npx shadcn@latest add https://fluidfunctionalism.com/r/chat-message.jsonSource
1"use client";23import { forwardRef, type ReactNode } from "react";4import { motion, type HTMLMotionProps } from "framer-motion";5import { cn } from "@/lib/utils";6import { spring } from "@/lib/springs";7import { useShape } from "@/lib/shape-context";8import { useTouchPrimary } from "@/hooks/use-touch-primary";9import { FileThumbnail } from "@/registry/default/file-thumbnail";1011interface ChatMessageProps12 extends Omit<HTMLMotionProps<"div">, "children"> {13 /** Who sent the message. Drives alignment and bubble colour:14 * `user` → right-aligned accent bubble, `assistant` → left-aligned plain text. */15 from: "user" | "assistant";16 /** Optional attachments rendered as square thumbnails above the bubble. */17 files?: File[];18 /** Side length of each attachment thumbnail in pixels. Defaults to 64. */19 thumbnailSize?: number;20 /** Timestamp shown in the hover-revealed meta row, before the actions.21 * User-message only — ignored on assistant replies. Caller pre-formats it22 * (e.g. `"Wednesday 6:08 PM"`). */23 time?: ReactNode;24 /** Icon-only action buttons shown in the hover-revealed meta row (e.g. copy,25 * edit, regenerate). Rendered next to the timestamp. */26 actions?: ReactNode;27 /** Message body. When omitted the text bubble is dropped (attachment-only message). */28 children?: ReactNode;29}3031// ─── ChatMessage ──────────────────────────────────────────────────────────32// A single transcript entry with baked-in entrance + layout motion. Pairs with33// InputMessage's onSend: render one per sent/received message. `layout="position"`34// lets earlier messages slide up smoothly when a new one is appended.35const ChatMessage = forwardRef<HTMLDivElement, ChatMessageProps>(36 (37 { from, files, thumbnailSize = 64, time, actions, children, className, ...props },38 ref39 ) => {40 const shape = useShape();41 const isUser = from === "user";42 // Hover-reveal is unreachable on touch — keep the meta row visible there.43 const isTouch = useTouchPrimary();44 // Timestamps are a user-message affordance; assistant replies show actions only.45 const showTime = isUser && time != null;4647 return (48 <motion.div49 ref={ref}50 layout="position"51 initial={{ opacity: 0, y: 8, scale: 0.96 }}52 animate={{ opacity: 1, y: 0, scale: 1 }}53 transition={spring.moderate}54// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from fluid-functionalism
All 53 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | fluid-functionalism | Components | Free | 3 deps | |
| Accordion (Base UI)accordion-base | fluid-functionalism | Components | Free | 3 deps | |
| Ask User Questionsask-user-questions | fluid-functionalism | Components | Free | 2 deps | |
| Badgebadge | fluid-functionalism | Components | Free | 1 dep | |
| Buttonbutton | fluid-functionalism | Components | Free | 4 deps | |
| Button (Base UI)button-base | fluid-functionalism | Components | Free | 4 deps | |
| Cardcard | fluid-functionalism | Components | Free | 1 dep | |
| Checkbox Groupcheckbox-group | fluid-functionalism | Components | Free | 2 deps |
