Search results
Web results from a search tool in three views: a full list, a compact list and an image grid, with the query and result count on top.
On this page
Site, title, snippet with the query in a heavier weight, and date. Switch to the compact list.
Installation
Usage
import { SearchResults } from "@/components/ui/chatcn/search-results"
<SearchResults
query="optimal line length for reading on screens"
results={results}
total={2140}
durationMs={420}
variant={view}
onVariantChange={setView}
/>Each result takes a url, a title and optionally a snippet, site, date and image. Query words are set in a heavier weight inside snippets, matched as whole words so line marks *lines* but never the line in *deadline*.
Examples
Image grid
Each frame holds a 4:3 placeholder from the first paint and fades the picture in over 200 ms once it decodes. A broken image keeps its frame.
Image results hold their frame while they load.
Loading, empty and error
Skeletons are static blocks in the exact shape of the current view: no shimmer, because shimmer belongs to status labels. Use loading only while you know which view will render.
Skeletons in the shape of the view, an empty search and a failed one.
Props
| Prop | Type | Notes |
|---|---|---|
results | SearchResult[] | url, title, snippet?, site?, domain?, favicon?, date?, image? |
query | string | Shown in the header and bolded in snippets |
total | number | Total matches from the API. Defaults to the number of results |
durationMs | number | Search time next to the count |
variant | "list" | "compact" | "images" | Default list |
onVariantChange | (variant) => void | Shows the view switcher |
variants | SearchResultsVariant[] | Views offered by the switcher |
loading | boolean | Skeleton rows in the shape of the view |
error, onRetry | ReactNode, () => void | Error state with Retry search |
onResultClick | (result, index, event) => void | Call event.preventDefault() to open results yourself |
highlight | boolean | Bold query words in snippets. Default true |
empty | ReactNode | Message for zero results |
locale | string | Dates and counts. Default en-US so server and client agree |
Keyboard
| Key | Action |
|---|---|
Tab | Move through result titles, then the view switcher |
Arrow keys | Change the view inside the switcher, like a radio group |
Enter | Open the focused result |
Accessibility
- The list is a labelled
sectionwith real links. The whole row is the hit area, while the title stays the accessible name. - The view switcher is a
radiogroupwith roving focus. Each icon button has a label. - The count is a polite live region: it says Searching, then the number of results once.
- Errors use a red icon next to the words Search failed, never color alone.
Motion
- Hover changes background and underline color over 150 ms. Nothing moves or scales.
- Images fade in over 200 ms once loaded. Switching views is instant, since it is a frequent action.