// Adapted from agentui (https://github.com/ashish200729/agentui), components/agents/message-bubble.tsx
// Copyright (c) 2026 Saurabh Chauhan. MIT License, see ./LICENSE-agentui.md
// 改造:去掉 motion 的 layout 动画与 render 克隆;变体底色换语义 token(soft = foreground 洗层,danger = destructive,
// warning 为新增);折叠遮罩用 mask-image 渐变到 transparent(不写十六进制),箭头旋转用 duration-base。
import { ChevronDown } from "lucide-react";
import { type ComponentPropsWithRef, createContext, useContext, useId, useState } from "react";
import { cn } from "~/lib/utils.ts";
import { CHEVRON_CLASS } from "./disclosure.tsx";
import { MessageSideContext } from "./message.tsx";
export type MessageBubbleVariant = "solid" | "soft" | "outline" | "ghost" | "danger" | "warning";
const BubbleContext = createContext<{ variant: MessageBubbleVariant; align: "start" | "end" }>({
variant: "soft",
align: "start",
});
export function MessageBubble({
variant = "soft",
align,
className,
...props
}: ComponentPropsWithRef<"div"> & { variant?: MessageBubbleVariant; align?: "start" | "end" }) {
const side = useContext(MessageSideContext);
const resolved = align ?? side ?? "start";
return (
);
}
const VARIANT: Record = {
solid: "bg-foreground text-background",
soft: "border border-border/60 bg-foreground/[0.05]",
outline: "border border-border/70",
ghost: "w-full max-w-none rounded-none border-0 px-0 py-0",
danger: "border border-destructive/40 bg-destructive/10 text-destructive",
warning: "border border-warning/40 bg-warning/10 text-warning",
};
export function MessageBubbleContent({ className, ...props }: ComponentPropsWithRef<"div">) {
const { variant } = useContext(BubbleContext);
return (
);
}
const CLAMP = {
2: "line-clamp-2",
3: "line-clamp-3",
4: "line-clamp-4",
5: "line-clamp-5",
6: "line-clamp-6",
} as const;
/** 长消息折叠:收起时按行截断并渐隐 */
export function MessageBubbleCollapsible({
collapsedLines = 4,
moreLabel = "展开",
lessLabel = "收起",
className,
children,
...props
}: ComponentPropsWithRef<"div"> & { collapsedLines?: 2 | 3 | 4 | 5 | 6; moreLabel?: string; lessLabel?: string }) {
const id = useId();
const [open, setOpen] = useState(false);
return (
{children}
);
}