A loading state for AI images that turns into the real picture when it arrives.
Press Generate and the frame opens as four cells, then keeps splitting the biggest one in two until it becomes the picture. Busy parts of the image sharpen first, and a status pill sits in the bottom left until it lands. Honors prefers-reduced-motion by holding a still frame.
Options you can pass to customize this component.
srcstringnullImage to reveal. Keep it null while the image is generating, since the grid only runs while this is empty and a src that is already loaded makes the whole run flash by.
altstringDescribes the finished image for screen readers. The frame is hidden from assistive tech when omitted.
progressnumberPosition of the wait from 0 to 1, driving how far the grid has split. It holds at 0.72 until the image decodes, and the image landing is what finishes the reveal.
aspectnumberWidth divided by height of the frame. The frame fills its parent's width, so constrain the parent to size it.
captionstringOptional status text, shown as a frosted pill in the bottom left of the frame and lit by a slow shimmer. Change it mid-run and the lines crossfade while the pill resizes to suit.
estimatedDurationnumberRoughly how long the work takes, used to pace the grid when no progress is passed. Overrunning it is fine, the grid keeps creeping instead of stopping.
onRevealComplete() => voidFires once the image has fully resolved.
onError() => voidFires when the image fails to load. Without it a broken src leaves the grid waiting, so use it to show your own fallback.
classNamestringExtra classes merged onto the root element (data-slot="grid-reveal").
npx shadcn@latest add swamimalode07/rare-ui/grid-reveal"use client"import { useState } from "react"import GridReveal from "@/components/ui/grid-reveal"export function Demo() {const [src, setSrc] = useState<string | null>(null)async function generate() {setSrc(null) // null is the waiting state, the grid runs while it is emptysetSrc(await createImage()) // setting it resolves the grid into the picture}return (// the frame fills its parent, so give the parent a width<div className="w-64"><GridReveal src={src} alt="Generated image" caption="Creating image" /><button onClick={generate}>Generate</button></div>)}// Passing a src that is already loaded skips the wait, so the run flashes by.// Pass progress when your API reports it: <GridReveal src={src} progress={job.progress} />
Click the code icon in the top-right corner to view the source code.
Most components here are recreations of great work from around the web. I don't claim to be the original creator - this is my attempt to reverse-engineer, replicate, and often add a few extra features. I've tried to credit everyone; if I missed someone, let me know.
1