From 444b5b33f0ea41980c1116e3d83e6667eed70f9d Mon Sep 17 00:00:00 2001 From: James Magahern Date: Sat, 14 Feb 2026 02:02:18 -0800 Subject: [PATCH] answers: collapsing behavior fixed height --- .../search/search-results-panel.tsx | 78 ++++++++++++++++--- 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/web/src/components/search/search-results-panel.tsx b/web/src/components/search/search-results-panel.tsx index cab81db..8337626 100644 --- a/web/src/components/search/search-results-panel.tsx +++ b/web/src/components/search/search-results-panel.tsx @@ -1,6 +1,8 @@ +import { useEffect, useRef, useState } from "preact/hooks"; import { Search } from "lucide-preact"; import type { SearchDetail, SearchResultItem } from "@/lib/api"; import { MarkdownContent } from "@/components/markdown/markdown-content"; +import { cn } from "@/lib/utils"; function cleanResultText(input: string) { return input @@ -50,6 +52,29 @@ type Props = { }; export function SearchResultsPanel({ search, isLoading, isRunning, showPrompt = true, className }: Props) { + const ANSWER_COLLAPSED_HEIGHT_CLASS = "h-[3rem]"; + const [isAnswerExpanded, setIsAnswerExpanded] = useState(false); + const [canExpandAnswer, setCanExpandAnswer] = useState(false); + const answerBodyRef = useRef(null); + + useEffect(() => { + setIsAnswerExpanded(false); + setCanExpandAnswer(false); + }, [search?.id, search?.answerText]); + + useEffect(() => { + const el = answerBodyRef.current; + if (!el || !search?.answerText) { + setCanExpandAnswer(false); + return; + } + if (isAnswerExpanded) { + setCanExpandAnswer(true); + return; + } + setCanExpandAnswer(el.scrollHeight - el.clientHeight > 1); + }, [search?.answerText, isAnswerExpanded]); + const citationEntries = (search?.answerCitations ?? []) .map((citation, index) => { const href = citation.url || citation.id || ""; @@ -68,6 +93,11 @@ export function SearchResultsPanel({ search, isLoading, isRunning, showPrompt = return citationEntries.find((entry) => entry.normalizedHref === normalized)?.index; }; + const hasAnswerText = !!search?.answerText; + const isAnswerLoading = isRunning && !hasAnswerText; + const hasCitations = citationEntries.length > 0; + const isExpandable = hasAnswerText && (canExpandAnswer || hasCitations); + return (
{search?.query ? ( @@ -84,17 +114,47 @@ export function SearchResultsPanel({ search, isLoading, isRunning, showPrompt = {(isRunning || !!search?.answerText || !!search?.answerError) && (

Answer

- {isRunning && !search?.answerText ?

Generating answer...

: null} - {search?.answerText ? ( - + {(isAnswerLoading || hasAnswerText) ? ( +
+
+
+ {isAnswerLoading ? ( +
Generating answer...
+ ) : ( + + )} +
+ {!isAnswerExpanded && (isExpandable || isAnswerLoading) ? ( +
+ ) : null} +
+
+ {isExpandable ? ( + + ) : null} +
+
) : null} {search?.answerError ?

{search.answerError}

: null} - {!!citationEntries.length && ( + {isAnswerExpanded && !!citationEntries.length && (
{citationEntries.slice(0, 8).map((citation) => { return (