"use client"; import { Button } from "../ui/button"; import { cn } from "../../src/lib/utils"; import { ArrowDownIcon, UserIcon } from "lucide-react"; import type { ComponentProps } from "react"; import { useCallback } from "react"; import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom"; export type ConversationProps = ComponentProps; export const Conversation = ({ className, ...props }: ConversationProps) => ( ); export type ConversationContentProps = ComponentProps< typeof StickToBottom.Content >; export const ConversationContent = ({ className, ...props }: ConversationContentProps) => ( ); export type ConversationEmptyStateProps = ComponentProps<"div"> & { title?: string; description?: string; icon?: React.ReactNode; }; export const ConversationEmptyState = ({ className, title = "No messages yet", description = "Start a conversation to see messages here", icon, children, ...props }: ConversationEmptyStateProps) => (
{children ?? ( <> {icon &&
{icon}
}

{title}

{description && (

{description}

)}
)}
); export type ConversationScrollButtonProps = ComponentProps; /** * Button to scroll to the bottom of the conversation. * Can be used standalone or within ConversationScrollButtons container. * When used standalone, it handles its own visibility based on isAtBottom. * When used in ConversationScrollButtons, the container manages visibility. */ export const ConversationScrollButton = ({ className, ...props }: ConversationScrollButtonProps) => { const { scrollToBottom } = useStickToBottomContext(); const handleScrollToBottom = useCallback(() => { scrollToBottom(); }, [scrollToBottom]); return ( ); }; /** * Data attribute used to mark the last user message element. * ChatInterface adds this attribute to the last user message for scroll targeting. */ export const LAST_USER_MESSAGE_ATTR = "data-last-user-message"; export type ConversationScrollToLastUserMessageButtonProps = ComponentProps; /** * Button to scroll to the last user message in the conversation. * Reference: Issue #3 - Provide a feature to locate the last human message */ export const ConversationScrollToLastUserMessageButton = ({ className, ...props }: ConversationScrollToLastUserMessageButtonProps) => { const handleScrollToLastUserMessage = useCallback(() => { // Find the last user message element by data attribute const lastUserMessage = document.querySelector(`[${LAST_USER_MESSAGE_ATTR}="true"]`); if (lastUserMessage) { lastUserMessage.scrollIntoView({ behavior: "smooth", block: "start" }); } }, []); return ( ); }; export type ConversationScrollButtonsProps = ComponentProps<"div"> & { /** Whether there are user messages to scroll to */ hasUserMessages?: boolean; }; /** * Container for scroll navigation buttons. * Renders scroll-to-last-user-message and scroll-to-bottom buttons side by side. * Reference: Issue #3 - Provide a feature to locate the last human message */ export const ConversationScrollButtons = ({ className, hasUserMessages = false, ...props }: ConversationScrollButtonsProps) => { const { isAtBottom } = useStickToBottomContext(); if (isAtBottom) return null; return (
{hasUserMessages && }
); };