diff --git a/frontend/src/components/assistant/ChatSidebar.tsx b/frontend/src/components/assistant/ChatSidebar.tsx
index d474e5e9..133f0a60 100644
--- a/frontend/src/components/assistant/ChatSidebar.tsx
+++ b/frontend/src/components/assistant/ChatSidebar.tsx
@@ -1,4 +1,4 @@
-import { Plus, Pin, Trash2, MessageSquare } from 'lucide-react'
+import { Plus, Pin, Trash2, MessageSquare, History, X } from 'lucide-react'
import { cn } from '@/lib/utils'
import type { ChatListItem } from '@/types/assistant-chat'
@@ -11,6 +11,8 @@ interface ChatSidebarProps {
onTogglePin: (id: string, pinned: boolean) => void
mobileOpen?: boolean
onMobileClose?: () => void
+ collapsed?: boolean
+ onToggleCollapse?: () => void
}
export function ChatSidebar({
@@ -22,6 +24,8 @@ export function ChatSidebar({
onTogglePin,
mobileOpen = false,
onMobileClose,
+ collapsed = false,
+ onToggleCollapse,
}: ChatSidebarProps) {
const pinnedChats = chats.filter(c => c.pinned)
const unpinnedChats = chats.filter(c => !c.pinned)
@@ -36,6 +40,11 @@ export function ChatSidebar({
onMobileClose?.()
}
+ // When collapsed on desktop, render nothing — parent renders the top bar
+ if (collapsed && !mobileOpen) {
+ return null
+ }
+
return (
<>
{/* Mobile overlay */}
@@ -52,14 +61,23 @@ export function ChatSidebar({
style={{ background: 'var(--color-bg-sidebar)' }}
>
{/* Header */}
-
+
+ {onToggleCollapse && (
+
+ )}
{/* Chat list */}
@@ -108,6 +126,51 @@ export function ChatSidebar({
)
}
+/** Collapsed top bar — rendered by the parent page above the chat area */
+export function ChatSidebarCollapsedBar({
+ chats,
+ activeChatId,
+ onNewChat,
+ onExpand,
+}: {
+ chats: ChatListItem[]
+ activeChatId: string | null
+ onNewChat: () => void
+ onExpand: () => void
+}) {
+ return (
+
+
+
+
+ {activeChatId && (
+
+ {chats.find(c => c.id === activeChatId)?.title}
+
+ )}
+
+ )
+}
+
function ChatItem({
chat,
isActive,
diff --git a/frontend/src/pages/AssistantChatPage.tsx b/frontend/src/pages/AssistantChatPage.tsx
index 05747412..c8de1740 100644
--- a/frontend/src/pages/AssistantChatPage.tsx
+++ b/frontend/src/pages/AssistantChatPage.tsx
@@ -10,7 +10,7 @@ import { aiSessionsApi } from '@/api/aiSessions'
import { useBranching } from '@/hooks/useBranching'
import { analytics } from '@/lib/analytics'
import { toast } from '@/lib/toast'
-import { ChatSidebar } from '@/components/assistant/ChatSidebar'
+import { ChatSidebar, ChatSidebarCollapsedBar } from '@/components/assistant/ChatSidebar'
import { ChatMessage } from '@/components/assistant/ChatMessage'
import { TaskLane } from '@/components/assistant/TaskLane'
import { ConcludeSessionModal } from '@/components/assistant/ConcludeSessionModal'
@@ -45,6 +45,14 @@ export default function AssistantChatPage() {
const [activeQuestions, setActiveQuestions] = useState
([])
const [activeActions, setActiveActions] = useState([])
const [showTaskLane, setShowTaskLane] = useState(false)
+ const [sidebarCollapsed, setSidebarCollapsed] = useState(() =>
+ localStorage.getItem('rf-chat-sidebar-collapsed') === 'true'
+ )
+ const toggleSidebarCollapse = () => {
+ const next = !sidebarCollapsed
+ setSidebarCollapsed(next)
+ localStorage.setItem('rf-chat-sidebar-collapsed', String(next))
+ }
const messagesEndRef = useRef(null)
const inputRef = useRef(null)
const fileInputRef = useRef(null)
@@ -470,17 +478,20 @@ export default function AssistantChatPage() {
<>
- {/* Sidebar — hidden on mobile, slide-out via toggle */}
-
-
-
+ {/* Sidebar — hidden on mobile, collapsed to top bar or full sidebar on desktop */}
+ {!sidebarCollapsed && (
+
+
+
+ )}
{/* Main chat area + optional branch sidebar */}
-
+
+
+ {/* Collapsed sidebar top bar — desktop only */}
+ {sidebarCollapsed && (
+
+
+
+ )}
+
+ {/* Chat content row: chat column + TaskLane side by side */}
+
{/* Mobile header with chat history toggle */}
@@ -555,7 +581,7 @@ export default function AssistantChatPage() {
{/* Rich Input */}
-
+
+
{/* close chat content row */}
+
{/* close outer flex-col */}
{/* Conclude Session Modal */}