add chat flow for search results

This commit is contained in:
2026-05-02 16:48:01 -07:00
parent fa429dcbb3
commit dc9336acf9
9 changed files with 322 additions and 28 deletions

View File

@@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from "preact/hooks";
import type { SearchDetail } from "@/lib/api";
import { MarkdownContent } from "@/components/markdown/markdown-content";
import { cn } from "@/lib/utils";
import { MessageSquare } from "lucide-preact";
function formatHost(url: string) {
try {
@@ -29,6 +30,8 @@ type Props = {
className?: string;
enableKeyboardNavigation?: boolean;
openLinksInNewTab?: boolean;
isStartingChat?: boolean;
onStartChat?: () => void;
};
export function SearchResultsPanel({
@@ -38,6 +41,8 @@ export function SearchResultsPanel({
className,
enableKeyboardNavigation = false,
openLinksInNewTab = true,
isStartingChat = false,
onStartChat,
}: Props) {
const ANSWER_COLLAPSED_HEIGHT_CLASS = "h-[3rem]";
const [isAnswerExpanded, setIsAnswerExpanded] = useState(false);
@@ -133,17 +138,31 @@ export function SearchResultsPanel({
const isAnswerLoading = isRunning && !hasAnswerText;
const hasCitations = citationEntries.length > 0;
const isExpandable = hasAnswerText && (canExpandAnswer || hasCitations);
const canStartChat = !!search && !isLoading && !isRunning && !isStartingChat && (!!search.answerText || search.results.length > 0);
return (
<div className={className ?? "mx-auto w-full max-w-4xl"}>
{search?.query ? (
<div className="mb-5">
<p className="text-sm text-muted-foreground">Results for</p>
<h2 className="mt-1 break-words text-xl font-semibold text-violet-50">{search.query}</h2>
<p className="mt-1 text-xs text-muted-foreground">
{search.results.length} result{search.results.length === 1 ? "" : "s"}
{search.latencyMs ? `${search.latencyMs} ms` : ""}
</p>
<div className="mb-5 flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
<div className="min-w-0">
<p className="text-sm text-muted-foreground">Results for</p>
<h2 className="mt-1 break-words text-xl font-semibold text-violet-50">{search.query}</h2>
<p className="mt-1 text-xs text-muted-foreground">
{search.results.length} result{search.results.length === 1 ? "" : "s"}
{search.latencyMs ? `${search.latencyMs} ms` : ""}
</p>
</div>
{onStartChat ? (
<button
type="button"
className="inline-flex h-10 shrink-0 items-center justify-center gap-2 rounded-lg border border-violet-300/24 bg-violet-300/10 px-3 text-sm font-medium text-violet-50 transition hover:bg-violet-300/16 disabled:cursor-not-allowed disabled:opacity-50"
onClick={onStartChat}
disabled={!canStartChat}
>
<MessageSquare className="h-4 w-4" />
{isStartingChat ? "Starting chat..." : "Chat with results"}
</button>
) : null}
</div>
) : null}