Search Results Swap
Stale answers dim and stay put while the fresh set cross-fades over them.
The animated component in this preview is rendered from the canonical file shown here. The surrounding demo shell only provides context and is not part of the copied code.
import { useEffect, useState } from "react";
import { AnimatePresence, motion, useReducedMotion } from "motion/react";
/**
* Vibary · Search Results Swap
*
* Results never leave the screen. While a fresh query is in flight the
* previous results stay, dimmed, and the new set cross-fades over them —About this pattern
Type-ahead's real failure is not slowness, it is emptiness: clearing the list on every keystroke makes a fast connection feel broken. Here the previous results never leave. They drop to roughly half opacity the moment a new request goes out — that dim is the loading state, so no spinner is needed — and the fresh set cross-fades over them with a small lift once it lands. Both sets share one grid cell, so the panel is sized by the taller of them while they cross and can never collapse between two queries. The query itself is echoed instantly, without animation: the user typed it, and animating their own input back at them reads as lag.
Where it shows up
Screens we drew to show where this motion usually sits. Illustrations, not captures of any product.
- Document page
Documentation results refresh under a changing query without emptying the panel.
Related patterns
- Skeleton to ContentBreathing placeholders hand off to the real content in one cross-fade and a small lift.
- Table Rows PopulatePlaceholder cells resolve one column at a time, so the eye follows the fill instead of hunting for it.
- Video Buffer RingThe frame dims and a turning arc holds over it, then dissolves outward on resume.