shadcn.io is not affiliated with official shadcn/ui
Search Results Skeleton Block for React
A rebate search that loads in place: a real search field and button over five results with titles, addresses and excerpts, marked where your words occur.
Installation
Overview
Show search results while they load, then swap them in without moving anything, with this search results skeleton for React with Base UI. A hairline frame with a plus mark on each corner holds a real search form, a count line and five results from Marquetry, a local-rebates finder. The field and its Search button are real from the first paint; the count, each title, address and two-line excerpt is a Skeleton bar that becomes the data in the same cell, row by row. Searching is the reload: Enter or the Search button runs your words over the five typed results, marks them with Search Highlight Text and keeps only the results that contain them. An unseen copy of all five holds the height, and a word nothing contains says so. The control is an outline Button, the bands are ruled by Guides, and a polite line says what loaded. For search pages and any result list that waits for a query.
FAQ
What stays local, and how do I wire it to a real query?
Nothing is fetched. The five results are typed in RESULTS, and a search is a plain case-insensitive match of your words against each title and excerpt, Load starts a 700 millisecond timer, and when it ends the phase becomes ready and the data swaps in; Reload goes back to the bars and in again. To wire it for real, delete the timer, the Load button and the polite line, and set data-state (loading or ready) and aria-busy on the region from your query's pending state, or use the bars as a Suspense fallback and render the real rows when they arrive. Replace resultsOf with your query's results and pass the same words to the highlighter. The bars are derived from the same array as the data, so keep one row component for both.
Why doesn't the page jump when the data arrives?
Each bar and its data sit in one grid cell, so the larger of the two sets the cell's box and the swap changes nothing around it. Under the shown results sits an unseen copy of all five, in the same grid cell, so a search that keeps two results leaves the panel as tall as one that keeps five. The count line and the excerpts are clamped, so no row changes height. The polite line under the panel reserves two lines, so the panel is exactly as tall before, during and after loading at every width.
How does the search work here?
The words you type are matched, ignoring case, as one phrase against the title and excerpt of each result, so "heat pump" keeps all five and "battery" keeps one. Pressing Enter or Search puts the panel back to loading and then shows the matches, marked. Blank words keep all five. Nothing is sent anywhere.
How are the words marked?
Each match is a real mark element drawn by the catalog's Search Highlight Text, tinted from the foreground rather than a status colour so it reads in any theme, and filled in one after another unless reduced motion is set. The results are plain text, not links, because there is nowhere to go.
Is it accessible?
The region is marked busy while it loads and carries a screen-reader-only "Loading results…", and the polite line announces what loaded once. The bars are hidden from assistive technology and the layer that isn't showing is invisible, so it is neither read nor focusable. The pulse stops when the data is in, and under reduced motion there is no pulse, no spinner and no stagger: the swap is instant.