import { IconDots, IconPlus } from "@tabler/icons-react"; import type { ReactNode } from "react"; import { ActionButton, IconButton } from "../design-system/components.js"; import { DesignSystemErrorBoundary } from "../design-system/error-boundary.js"; import { ChatHistoryList, type ChatHistoryItem, type ChatHistoryListProps, } from "./ChatHistoryList.js"; import { type ChatHistoryRailController, useChatHistoryRailController, } from "./useChatHistoryRailController.js"; export interface ChatHistoryRailLabels { newChat: string; showMore: string; showLess: string; } export interface ChatHistoryRailProps extends Omit< ChatHistoryListProps, "footer" | "items" | "sections" | "variant" > { items: ChatHistoryItem[]; onNewChat: () => void; railLabels: ChatHistoryRailLabels; previewCount?: number; expandedCount?: number; /** * Product-level presentation slot for design systems that want to replace * the rail wholesale. State and actions still come from the same controller * as the default view. */ renderRail?: (context: ChatHistoryRailRenderContext) => ReactNode; } export interface ChatHistoryRailRenderContext { controller: ChatHistoryRailController; listProps: Omit< ChatHistoryListProps, "footer" | "items" | "sections" | "variant" >; } export type DefaultChatHistoryRailViewProps = ChatHistoryRailRenderContext; export function DefaultChatHistoryRailView({ controller, listProps, }: ChatHistoryRailRenderContext) { const { canExpand, disclosureLabel, expanded, newChatLabel, onNewChat, toggleExpanded, visibleItems, } = controller; const { className, emptyLabel, ...rest } = listProps; const footer = (
{canExpand && (
); return ( ); } /** * Compact recent-chat rail for app sidebars. Hosts own thread persistence, * sorting, routing, and mutations; the rail only owns progressive disclosure. */ export function ChatHistoryRail({ items, onNewChat, railLabels, previewCount = 5, expandedCount = 15, renderRail, className, emptyLabel, ...listProps }: ChatHistoryRailProps) { const controller = useChatHistoryRailController({ items, onNewChat, labels: railLabels, previewCount, expandedCount, }); const context: ChatHistoryRailRenderContext = { controller, listProps: { ...listProps, className, emptyLabel }, }; const fallback = ; return renderRail ? ( ) : ( fallback ); } function ChatHistoryRailCustomView({ renderRail, context, }: { renderRail: NonNullable; context: ChatHistoryRailRenderContext; }) { return renderRail(context); }