mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-06-03 19:25:19 +02:00
add chat sidebar icon and refactor open and close logic
This commit is contained in:
parent
5cc8b4bb79
commit
a5cb47c885
2 changed files with 35 additions and 30 deletions
|
|
@ -6,7 +6,7 @@ import type { LanguageModelUsage, ToolUIPart } from 'ai';
|
||||||
import './App.css'
|
import './App.css'
|
||||||
import z from 'zod';
|
import z from 'zod';
|
||||||
import { Button } from './components/ui/button';
|
import { Button } from './components/ui/button';
|
||||||
import { CheckIcon, LoaderIcon, ArrowUp } from 'lucide-react';
|
import { CheckIcon, LoaderIcon, ArrowUp, PanelRightIcon } from 'lucide-react';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { MarkdownEditor } from './components/markdown-editor';
|
import { MarkdownEditor } from './components/markdown-editor';
|
||||||
import { ChatInputBar } from './components/chat-button';
|
import { ChatInputBar } from './components/chat-button';
|
||||||
|
|
@ -334,7 +334,7 @@ function App() {
|
||||||
})
|
})
|
||||||
const [graphStatus, setGraphStatus] = useState<'idle' | 'loading' | 'ready' | 'error'>('idle')
|
const [graphStatus, setGraphStatus] = useState<'idle' | 'loading' | 'ready' | 'error'>('idle')
|
||||||
const [graphError, setGraphError] = useState<string | null>(null)
|
const [graphError, setGraphError] = useState<string | null>(null)
|
||||||
const [isChatSidebarOpen, setIsChatSidebarOpen] = useState(false)
|
const [isChatSidebarOpen, setIsChatSidebarOpen] = useState(true)
|
||||||
|
|
||||||
// Auto-save state
|
// Auto-save state
|
||||||
const [isSaving, setIsSaving] = useState(false)
|
const [isSaving, setIsSaving] = useState(false)
|
||||||
|
|
@ -1120,15 +1120,15 @@ function App() {
|
||||||
knowledgeActions={knowledgeActions}
|
knowledgeActions={knowledgeActions}
|
||||||
/>
|
/>
|
||||||
<SidebarInset className="overflow-hidden! min-h-0">
|
<SidebarInset className="overflow-hidden! min-h-0">
|
||||||
{/* Header with sidebar trigger */}
|
{/* Header with sidebar triggers */}
|
||||||
<header className="flex h-12 shrink-0 items-center gap-2 border-b border-border px-3 bg-background">
|
<header className="flex h-12 shrink-0 items-center gap-2 border-b border-border px-3 bg-background">
|
||||||
<SidebarTrigger className="-ml-1" />
|
<SidebarTrigger className="-ml-1" />
|
||||||
<Separator orientation="vertical" className="h-4" />
|
<Separator orientation="vertical" className="h-4" />
|
||||||
<span className="text-sm font-medium text-muted-foreground">
|
<span className="text-sm font-medium text-muted-foreground flex-1">
|
||||||
{headerTitle}
|
{headerTitle}
|
||||||
</span>
|
</span>
|
||||||
{selectedPath && (
|
{selectedPath && (
|
||||||
<div className="flex items-center gap-1 text-xs text-muted-foreground ml-auto">
|
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
||||||
{isSaving ? (
|
{isSaving ? (
|
||||||
<>
|
<>
|
||||||
<LoaderIcon className="h-3 w-3 animate-spin" />
|
<LoaderIcon className="h-3 w-3 animate-spin" />
|
||||||
|
|
@ -1147,11 +1147,25 @@ function App() {
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => setIsGraphOpen(false)}
|
onClick={() => setIsGraphOpen(false)}
|
||||||
className="ml-auto text-foreground"
|
className="text-foreground"
|
||||||
>
|
>
|
||||||
Close Graph
|
Close Graph
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
{(selectedPath || isGraphOpen) && (
|
||||||
|
<>
|
||||||
|
<Separator orientation="vertical" className="h-4" />
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => setIsChatSidebarOpen(!isChatSidebarOpen)}
|
||||||
|
className="size-7 -mr-1"
|
||||||
|
>
|
||||||
|
<PanelRightIcon />
|
||||||
|
<span className="sr-only">Toggle Chat Sidebar</span>
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{isGraphOpen ? (
|
{isGraphOpen ? (
|
||||||
|
|
@ -1243,10 +1257,10 @@ function App() {
|
||||||
</SidebarInset>
|
</SidebarInset>
|
||||||
|
|
||||||
{/* Chat sidebar - shown when viewing files/graph */}
|
{/* Chat sidebar - shown when viewing files/graph */}
|
||||||
{isChatSidebarOpen && (selectedPath || isGraphOpen) && (
|
{(selectedPath || isGraphOpen) && (
|
||||||
<ChatSidebar
|
<ChatSidebar
|
||||||
defaultWidth={400}
|
defaultWidth={400}
|
||||||
onClose={() => setIsChatSidebarOpen(false)}
|
isOpen={isChatSidebarOpen}
|
||||||
onNewChat={handleNewChat}
|
onNewChat={handleNewChat}
|
||||||
conversation={conversation}
|
conversation={conversation}
|
||||||
currentAssistantMessage={currentAssistantMessage}
|
currentAssistantMessage={currentAssistantMessage}
|
||||||
|
|
@ -1255,9 +1269,6 @@ function App() {
|
||||||
message={message}
|
message={message}
|
||||||
onMessageChange={setMessage}
|
onMessageChange={setMessage}
|
||||||
onSubmit={handlePromptSubmit}
|
onSubmit={handlePromptSubmit}
|
||||||
contextUsage={contextUsage}
|
|
||||||
maxTokens={maxTokens}
|
|
||||||
usedTokens={usedTokens}
|
|
||||||
knowledgeFiles={knowledgeFiles}
|
knowledgeFiles={knowledgeFiles}
|
||||||
recentFiles={recentWikiFiles}
|
recentFiles={recentWikiFiles}
|
||||||
visibleFiles={visibleKnowledgeFiles}
|
visibleFiles={visibleKnowledgeFiles}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { ArrowUp, PanelRightClose, Plus } from 'lucide-react'
|
import { ArrowUp, Plus } from 'lucide-react'
|
||||||
import type { LanguageModelUsage, ToolUIPart } from 'ai'
|
import type { ToolUIPart } from 'ai'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import {
|
import {
|
||||||
|
|
@ -103,7 +103,7 @@ const DEFAULT_WIDTH = 400
|
||||||
|
|
||||||
interface ChatSidebarProps {
|
interface ChatSidebarProps {
|
||||||
defaultWidth?: number
|
defaultWidth?: number
|
||||||
onClose: () => void
|
isOpen?: boolean
|
||||||
onNewChat: () => void
|
onNewChat: () => void
|
||||||
conversation: ConversationItem[]
|
conversation: ConversationItem[]
|
||||||
currentAssistantMessage: string
|
currentAssistantMessage: string
|
||||||
|
|
@ -112,9 +112,6 @@ interface ChatSidebarProps {
|
||||||
message: string
|
message: string
|
||||||
onMessageChange: (message: string) => void
|
onMessageChange: (message: string) => void
|
||||||
onSubmit: (message: PromptInputMessage, mentions?: FileMention[]) => void
|
onSubmit: (message: PromptInputMessage, mentions?: FileMention[]) => void
|
||||||
contextUsage: LanguageModelUsage
|
|
||||||
maxTokens: number
|
|
||||||
usedTokens: number
|
|
||||||
knowledgeFiles?: string[]
|
knowledgeFiles?: string[]
|
||||||
recentFiles?: string[]
|
recentFiles?: string[]
|
||||||
visibleFiles?: string[]
|
visibleFiles?: string[]
|
||||||
|
|
@ -123,7 +120,7 @@ interface ChatSidebarProps {
|
||||||
|
|
||||||
export function ChatSidebar({
|
export function ChatSidebar({
|
||||||
defaultWidth = DEFAULT_WIDTH,
|
defaultWidth = DEFAULT_WIDTH,
|
||||||
onClose,
|
isOpen = true,
|
||||||
onNewChat,
|
onNewChat,
|
||||||
conversation,
|
conversation,
|
||||||
currentAssistantMessage,
|
currentAssistantMessage,
|
||||||
|
|
@ -396,10 +393,15 @@ export function ChatSidebar({
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const displayWidth = isOpen ? width : 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="relative flex flex-col border-l border-border bg-background shrink-0"
|
className={cn(
|
||||||
style={{ width }}
|
"relative flex flex-col border-l border-border bg-background shrink-0 overflow-hidden",
|
||||||
|
!isResizing && "transition-[width] duration-200 ease-linear"
|
||||||
|
)}
|
||||||
|
style={{ width: displayWidth }}
|
||||||
>
|
>
|
||||||
{/* Resize handle */}
|
{/* Resize handle */}
|
||||||
<div
|
<div
|
||||||
|
|
@ -412,16 +414,8 @@ export function ChatSidebar({
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Header - minimal, no border */}
|
{/* Header - minimal, just new chat button */}
|
||||||
<header className="flex h-12 shrink-0 items-center justify-between px-2">
|
<header className="flex h-12 shrink-0 items-center justify-end px-2">
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<Button variant="ghost" size="icon" onClick={onClose} className="h-8 w-8 text-muted-foreground hover:text-foreground">
|
|
||||||
<PanelRightClose className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent side="bottom">Close</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<Button variant="ghost" size="icon" onClick={onNewChat} className="h-8 w-8 text-muted-foreground hover:text-foreground">
|
<Button variant="ghost" size="icon" onClick={onNewChat} className="h-8 w-8 text-muted-foreground hover:text-foreground">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue