"use client"; import { MessageInput, MessageInputTextarea, MessageInputToolbar, MessageInputSubmitButton, MessageInputError, // MessageInputMcpConfigButton, } from "@/components/ui/message-input"; import { MessageSuggestions, MessageSuggestionsStatus, MessageSuggestionsList, } from "@/components/ui/message-suggestions"; import type { messageVariants } from "@/components/ui/message"; import { ThreadContent, ThreadContentMessages, } from "@/components/ui/thread-content"; import { ThreadDropdown } from "@/components/ui/thread-dropdown"; import { ScrollableMessageContainer } from "@/components/ui/scrollable-message-container"; import { cn } from "@/lib/utils"; import { Collapsible } from "radix-ui"; import { XIcon } from "lucide-react"; import * as React from "react"; import { type VariantProps } from "class-variance-authority"; import type { Suggestion } from "@tambo-ai/react"; /** * Props for the MessageThreadCollapsible component * @interface * @extends React.HTMLAttributes */ export interface MessageThreadCollapsibleProps extends React.HTMLAttributes { /** Optional context key for the thread */ contextKey?: string; /** Whether the collapsible should be open by default (default: false) */ defaultOpen?: boolean; /** * Controls the visual styling of messages in the thread. * Possible values include: "default", "compact", etc. * These values are defined in messageVariants from "@/components/ui/message". * @example variant="compact" */ variant?: VariantProps["variant"]; } /** * A collapsible chat thread component with keyboard shortcuts and thread management * @component * @example * ```tsx * * ``` */ /** * Custom hook for managing collapsible state with keyboard shortcuts */ const useCollapsibleState = (defaultOpen = false) => { const [isOpen, setIsOpen] = React.useState(defaultOpen); const isMac = typeof navigator !== "undefined" && navigator.platform.startsWith("Mac"); const shortcutText = isMac ? "⌘K" : "Ctrl+K"; React.useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if ((event.metaKey || event.ctrlKey) && event.key === "k") { event.preventDefault(); setIsOpen((prev) => !prev); } }; document.addEventListener("keydown", handleKeyDown); return () => document.removeEventListener("keydown", handleKeyDown); }, []); return { isOpen, setIsOpen, shortcutText }; }; /** * Props for the CollapsibleContainer component */ interface CollapsibleContainerProps extends React.HTMLAttributes { isOpen: boolean; onOpenChange: (open: boolean) => void; children: React.ReactNode; } /** * Container component for the collapsible panel */ const CollapsibleContainer = React.forwardRef< HTMLDivElement, CollapsibleContainerProps >(({ className, isOpen, onOpenChange, children, ...props }, ref) => ( {children} )); CollapsibleContainer.displayName = "CollapsibleContainer"; /** * Props for the CollapsibleTrigger component */ interface CollapsibleTriggerProps { isOpen: boolean; shortcutText: string; onClose: () => void; contextKey?: string; onThreadChange: () => void; config: { labels: { openState: string; closedState: string; }; }; } /** * Trigger component for the collapsible panel */ const CollapsibleTrigger = ({ isOpen, shortcutText, onClose, contextKey, onThreadChange, config, }: CollapsibleTriggerProps) => ( <> {!isOpen && ( )} {isOpen && (
{config.labels.openState}
)} ); CollapsibleTrigger.displayName = "CollapsibleTrigger"; export const MessageThreadCollapsible = React.forwardRef< HTMLDivElement, MessageThreadCollapsibleProps >(({ className, contextKey, defaultOpen = false, variant, ...props }, ref) => { const { isOpen, setIsOpen, shortcutText } = useCollapsibleState(defaultOpen); const handleThreadChange = React.useCallback(() => { setIsOpen(true); }, [setIsOpen]); /** * Configuration for the MessageThreadCollapsible component */ const THREAD_CONFIG = { labels: { openState: "Conversations", closedState: "Start chatting with tambo", }, }; const defaultSuggestions: Suggestion[] = [ { id: "suggestion-1", title: "Get started", detailedSuggestion: "What can you help me with?", messageId: "welcome-query", }, { id: "suggestion-2", title: "Learn more", detailedSuggestion: "Tell me about your capabilities.", messageId: "capabilities-query", }, { id: "suggestion-3", title: "Examples", detailedSuggestion: "Show me some example queries I can try.", messageId: "examples-query", }, ]; return ( setIsOpen(false)} contextKey={contextKey} onThreadChange={handleThreadChange} config={THREAD_CONFIG} />
{/* Message thread content */} {/* Message Suggestions Status */} {/* Message input */}
{/* Uncomment this to enable client-side MCP config modal button */} {/* */}
{/* Message suggestions */}
); }); MessageThreadCollapsible.displayName = "MessageThreadCollapsible";