Web Search
An AI agent’s web research as a live timeline: searches, pages opened, sources as overlapping site marks, errors and retry.
Overview
Shows where an agent went while it researched. Each search appears with its query and, when it lands, the result count and the sources it kept, drawn as overlapping site marks that expand into a list of linked pages with titles and snippets. Pages it opened appear as reads, with an optional one-line takeaway.
While the agent works, the header shimmers with what it is doing right now and a live timer; running steps spin and shimmer, the rail draws itself down as new steps arrive, and a failed search turns red with the reason and a retry button. When research ends, the header summarises it (“Researched 3 searches, 2 pages · 9 sites”) and can collapse to that line.
Everything comes from props: append steps and update their status from your agent’s tool events. Favicons are optional; without them each site gets a lettered mark in a stable colour.
When to use
- Agents and assistants that search the web or a knowledge base before answering.
- Making long research tasks feel transparent and checkable.
When not to use
- Showing the reasoning itself: use Reasoning Trace.
- A single search box with results: use Search Field.
Installation
pnpm dlx shadcn@latest add https://sundaeui.dev/r/web-search.jsonnpx shadcn@latest add https://sundaeui.dev/r/web-search.jsonyarn dlx shadcn@latest add https://sundaeui.dev/r/web-search.jsonbunx --bun shadcn@latest add https://sundaeui.dev/r/web-search.jsonWorks in any React project. Files are written to components/sundae/. Read the source in the stage’s Code view. Pro assets need a personal token. See authenticated installs.
- No dependencies beyond React 18 or later.
- Copy web-search.tsx and web-search.css into components/sundae/.
- The CSS file is imported by the component, so no extra configuration is needed.
- Import the component and use it as shown below.
Usage
import { WebSearch, type ResearchStep } from '@/components/sundae/web-search'
// Build steps from your agent's tool events as they stream in.
const [steps, setSteps] = useState<ResearchStep[]>([])
onToolStart((call) => setSteps((s) => [...s, call.name === 'web_search'
? { id: call.id, kind: 'search', query: call.input.query, status: 'running' }
: { id: call.id, kind: 'read', url: call.input.url, status: 'running' }]))
onToolResult((r) => setSteps((s) => s.map((x) => x.id === r.id
? { ...x, status: 'done', resultCount: r.total, sources: r.results.map((h) => ({ url: h.url, title: h.title, snippet: h.snippet })) }
: x)))
<WebSearch steps={steps} status={done ? 'done' : 'running'} startedAt={startedAt} endedAt={endedAt} onRetry={retry} />Props
| Prop | Type | Default |
|---|---|---|
steps*Searches ({ kind: 'search', query, resultCount, sources }) and reads ({ kind: 'read', url, title, summary }), each with id and status: pending, running, done or error. | ResearchStep[] | — |
status*Overall state: running shows the shimmer and live timer. | 'running' | 'done' | 'error' | — |
startedAtDate.now() when research began; drives the timer. | number | — |
endedAtWhen it finished, for the final duration. | number | — |
onRetryShows Retry on failed steps. | (stepId: string) => void | — |
collapseOnDoneCollapse to the summary line when finished. | boolean | false |
defaultOpenStart expanded. | boolean | true |
maxMarksSite marks shown per search before “+N”. | number | 4 |
themeauto follows a .dark ancestor. | 'auto' | 'light' | 'dark' | 'auto' |
Accessibility
- The header and each “N sources” row are buttons with aria-expanded controlling their panels; collapsed panels are inert.
- A polite live region announces what the agent is doing now (“Searching for …”, “Reading …”) and the final summary, not every update.
- Source links say they open in a new tab.
- Reduced motion removes shimmer, spinners, the drawing rail and entrances.
Customization
- Colours are custom properties on .sd-ws: --ws-accent, --ws-err, --ws-rail, --ws-ink, --ws-line.
- Pass favicon URLs on sources to use real site icons; lettered marks are the fallback.
- SiteMark and domainOf are exported for your own source lists.
FAQ
- Is Web Search free?
- Web Search is part of Sundae Pro. The live preview is open to everyone; the source installs with a Pro account.
- How do I install Web Search?
- Run npx shadcn@latest add https://sundaeui.dev/r/web-search.json. The files are written to components/sundae/. It has no dependencies beyond React 18 or later.
- Does Web Search support keyboard and screen readers?
- The header and each “N sources” row are buttons with aria-expanded controlling their panels; collapsed panels are inert. A polite live region announces what the agent is doing now (“Searching for …”, “Reading …”) and the final summary, not every update.
- Does Web Search respect reduced motion?
- Reduced motion removes shimmer, spinners, the drawing rail and entrances.
More like this
All components →- Pro
Reasoning Trace
Components · Refined - Pro
Cited Answer
Components · Refined Agent Steps
Components · Understated- Pro
Composer Attachments
Components · Refined Agent Thinking
Components · Refined- Pro
Tool Call
Components · Refined