/* Copyright 2026 Marimo. All rights reserved. */
import type { FileUIPart } from "ai";
import {
AtSignIcon,
FileIcon,
FileTextIcon,
ImageIcon,
PaperclipIcon,
SendHorizontalIcon,
StopCircleIcon,
XIcon,
} from "lucide-react";
import { useState } from "react";
import { cn } from "@/utils/cn";
import { Spinner } from "../icons/spinner";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import { Tooltip } from "../ui/tooltip";
import { SUPPORTED_ATTACHMENT_TYPES } from "./chat-utils";
export const AttachmentRenderer = ({
attachment,
}: {
attachment: FileUIPart;
}) => {
if (attachment.mediaType?.startsWith("image/")) {
return (
);
}
return (
{attachment.filename || "Attachment"}
);
};
export const FileAttachmentPill = ({
file,
className,
onRemove,
}: {
file: File;
className?: string;
onRemove: () => void;
}) => {
const [isHovered, setIsHovered] = useState(false);
return (
setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{isHovered ? (
) : (
renderFileIcon(file)
)}
{file.name}
);
};
export const SendButton = ({
isLoading,
onStop,
onSendClick,
isEmpty,
showStopLabel = false, // Show a stop label and spinner instead of just the stop icon when loading
}: {
isLoading: boolean;
onStop: () => void;
onSendClick: () => void;
isEmpty: boolean;
showStopLabel?: boolean;
}) => {
const loadingContent = showStopLabel ? (
Stop
) : (
);
return (
);
};
export const AddContextButton = ({
handleAddContext,
isLoading,
}: {
handleAddContext: () => void;
isLoading: boolean;
}) => {
return (
);
};
export const AttachFileButton = ({
fileInputRef,
isLoading,
onAddFiles,
}: {
fileInputRef: React.RefObject;
isLoading: boolean;
onAddFiles: (files: File[]) => void;
}) => {
return (
<>
) => {
if (event.target.files) {
onAddFiles([...event.target.files]);
}
}}
accept={SUPPORTED_ATTACHMENT_TYPES.join(",")}
/>
>
);
};
function renderFileIcon(file: File): React.ReactNode {
const classNames = "h-3 w-3 mt-0.5";
if (file.type.startsWith("image/")) {
return ;
} else if (file.type.startsWith("text/")) {
return ;
}
return ;
}