Template
Improve chat navigation, model selection, and streaming
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { RiCheckLine, RiSearchLine } from '@remixicon/react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from '@/components/ui/command';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@/components/ui/dialog';
|
||||
import type { StoredChat } from '@/services/indexed-db/chat-store';
|
||||
|
||||
interface ChatSearchProps {
|
||||
chats: StoredChat[];
|
||||
activeChatId: string | null;
|
||||
onSelectChat: (chatId: string) => void;
|
||||
}
|
||||
|
||||
export function ChatSearch({ chats, activeChatId, onSelectChat }: ChatSearchProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button type="button" variant="ghost" size="icon" className="size-7" aria-label="Search chats">
|
||||
<RiSearchLine className="size-5" aria-hidden="true" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-[calc(100%-2rem)] overflow-hidden p-0 sm:max-w-lg [&>button]:top-2.5">
|
||||
<DialogTitle className="sr-only">Search chats</DialogTitle>
|
||||
<DialogDescription className="sr-only">
|
||||
Search your saved chats by title and select one to continue the conversation.
|
||||
</DialogDescription>
|
||||
<Command>
|
||||
<CommandInput placeholder="Search chats..." aria-label="Search chats" className="pr-10" />
|
||||
<CommandList className="max-h-[min(24rem,60dvh)]">
|
||||
<CommandEmpty>
|
||||
{chats.length === 0 ? 'No chats yet. Start a new chat to get started.' : 'No chats found.'}
|
||||
</CommandEmpty>
|
||||
<CommandGroup heading="Recent chats">
|
||||
{chats.map((chat) => (
|
||||
<CommandItem
|
||||
key={chat.id}
|
||||
value={chat.id}
|
||||
keywords={[chat.title]}
|
||||
onSelect={() => {
|
||||
setOpen(false);
|
||||
onSelectChat(chat.id);
|
||||
}}
|
||||
>
|
||||
<span className="min-w-0 flex-1 truncate">{chat.title}</span>
|
||||
{chat.id === activeChatId && (
|
||||
<>
|
||||
<RiCheckLine className="size-4" aria-hidden="true" />
|
||||
<span className="sr-only">Current chat</span>
|
||||
</>
|
||||
)}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user