Grid Reveal

A loading state for AI images that turns into the real picture when it arrives.

Dependencies

motion

Interaction Type

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.

Props

Options you can pass to customize this component.

Prop
Type
Description
src
stringnull

Image 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.

alt
string

Describes the finished image for screen readers. The frame is hidden from assistive tech when omitted.

progress
number

Position 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.

aspect
number

Width divided by height of the frame. The frame fills its parent's width, so constrain the parent to size it.

caption
string

Optional 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.

estimatedDuration
number

Roughly 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
() => void

Fires once the image has fully resolved.

onError
() => void

Fires when the image fails to load. Without it a broken src leaves the grid waiting, so use it to show your own fallback.

className
string

Extra classes merged onto the root element (data-slot="grid-reveal").

Installation

npx shadcn@latest add swamimalode07/rare-ui/grid-reveal

How to use

"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 empty
setSrc(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} />

Source Code

Click the code icon in the top-right corner to view the source code.

Keep in mind

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.

Contact

Found a bug or issue? Feel free to drop a DM.

License & Usage

  • Free to use and modify in both personal and commercial projects.
  • Attribution to Rare UI is appreciated when using a component.
  • Please don't resell the components as your own kit.
Grid Reveal
Starting to generate