Aaditya

Denoise Reveal

Component

About

An image resolving out of noise like a diffusion model: noise falls and detail rises with each reported step, reseeded per step. Drive it by your sampler's progress or a timer.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Denoise Reveal to your project and fits it to your theme.

Code

How Denoise Reveal is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client"

import * as React from "react"
import { cn } from "@/lib/utils"
import { Button, DenoiseReveal, RotateCcwIcon } from "@/components/ui/denoise-reveal"

/** A run counter: bump it to remount a reveal and play it again from the first frame. */
function useRun() {
  const [run, setRun] = React.useState(0)
  return [run, React.useCallback(() => setRun((n) => n + 1), [])] as const
}

interface SimulatedJob {
  /** 0 to 1, or null before the first step reports. */
  progress: number | null
  step: number
  total: number
  running: boolean
  start: () => void
}

/**
 * A generation job on a script: queued for a beat with no numbers, then diffusion steps that
 * arrive every 60 to 170 ms, one stall of about a second, then done.
 */
function useSimulatedJob({ total = 30, autoStart = true, seed = 7 } = {}): SimulatedJob {
  const [step, setStep] = React.useState(-1)
  const [runId, setRunId] = React.useState(autoStart ? 1 : 0)
  React.useEffect(() => {
    if (!runId) return
    let alive = true
    let s = -1
    let r = (seed * 9301 + runId * 49297) % 233280
    const rand = () => {
      r = (r * 9301 + 49297) % 233280
      return r / 233280
    }
    setStep(-1)
    const tick = () => {
      if (!alive || s >= total) return
      s += 1
      setStep(s)
      const stall = s === Math.round(total * 0.62) ? 900 : 0
      timer = window.setTimeout(tick, 60 + rand() * 110 + stall)
    }
    let timer = window.setTimeout(tick, 700)
    return () => {
      alive = false
      window.clearTimeout(timer)
    }
  }, [runId, total, seed])
  // Reset the step in the same render as the new run, so a remounted reveal never sees the old 100%.
  const start = React.useCallback(() => {
    setStep(-1)
    setRunId((n) => n + 1)
  }, [])
  return {
    progress: step < 0 ? null : step / total,
    step: Math.max(0, step),
    total,
    running: runId > 0 && step < total,
    start,
  }
}

const STEPS = 30

const reducedMotion = () =>
  typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches

/** Calls `callback` every `ms`, for demos that replay on their own. Reduced motion never does. */
function useEvery(callback: () => void, ms: number) {
  const latest = React.useRef(callback)
  React.useEffect(() => {
    latest.current = callback
  })
  React.useEffect(() => {
    if (reducedMotion()) return
    const id = window.setInterval(() => latest.current(), ms)
    return () => window.clearInterval(id)
  }, [ms])
}

const FIT_CSS = "html,body{overflow:hidden}[data-fit-small] [data-fit-hide]{display:none!important}"

/**
 * 21st shows a demo in a small frame: about 674 by 421 on a component page, 358 by 224 on a
 * phone and 245 by 139 on a profile card. A demo taller than its frame gets scrollbars, which
 * render white on dark pages. FitFrame fills the frame exactly instead.
 *
 * - "scale": the content shrinks until it fits, centered. For visuals such as orbs.
 * - "crop": the content stays at full size from the top and fades out at the bottom. For text
 *   that streams in, where a changing scale would make the page breathe.
 *
 * Anything marked `data-fit-hide` (state buttons, the chatcn.dev line) drops out in frames
 * shorter than `hideBelow`, so a profile card shows the visual alone.
 */
function FitFrame({
  children,
  mode = "scale",
  hideBelow = 360,
}: {
  children: React.ReactNode
  mode?: "scale" | "crop"
  hideBelow?: number
}) {
  const content = React.useRef<HTMLDivElement>(null)
  const [cropped, setCropped] = React.useState(false)

  React.useLayoutEffect(() => {
    const el = content.current
    if (!el) return
    const measure = () => {
      const vw = window.innerWidth
      const vh = window.innerHeight
      el.toggleAttribute("data-fit-small", vh < hideBelow)
      // Layout sizes ignore the transform, so measuring never feeds back.
      const w = Math.max(el.offsetWidth, el.scrollWidth)
      const h = Math.max(el.offsetHeight, el.scrollHeight)
      const scale = mode === "scale" ? Math.min(1, vw / w, vh / h) : 1
      el.style.transform = scale < 1 ? `scale(${scale})` : ""
      setCropped(mode === "crop" && h > vh + 1)
    }
    measure()
    const observer = new ResizeObserver(measure)
    observer.observe(el)
    window.addEventListener("resize", measure)
    return () => {
      observer.disconnect()
      window.removeEventListener("resize", measure)
    }
  }, [mode, hideBelow])

  const fade = "linear-gradient(to bottom, #000 calc(100% - 40px), transparent)"
  return (
    <div
      className="flex w-full justify-center overflow-hidden"
      style={{
        height: "100dvh",
        alignItems: mode === "crop" ? "flex-start" : "center",
        maskImage: cropped ? fade : undefined,
        WebkitMaskImage: cropped ? fade : undefined,
      }}
    >
      <style>{FIT_CSS}</style>
      <div
        ref={content}
        className="w-full shrink-0"
        style={{ transformOrigin: mode === "crop" ? "top center" : "center" }}
      >
        {children}
      </div>
    </div>
  )
}

function ReplayButton({
  onClick,
  label = "Replay reveal",
  className,
}: {
  onClick: () => void
  label?: string
  className?: string
}) {
  return (
    <Button variant="outline" size="sm" onClick={onClick} className={className}>
      <RotateCcwIcon aria-hidden />
      {label}
    </Button>
  )
}

/** Media on top, an optional caption, then controls with the replay button at the end. */
function DemoShell({
  media,
  caption,
  controls,
  onReplay,
  replayLabel,
  className,
}: {
  media: React.ReactNode
  caption?: React.ReactNode
  controls?: React.ReactNode
  onReplay: () => void
  replayLabel?: string
  className?: string
}) {
  return (
    <div className={cn("flex w-full max-w-md flex-col gap-4", className)}>
      {media}
      {caption}
      <div className="flex flex-wrap items-end justify-between gap-3">
        <div className="flex flex-wrap items-end gap-x-4 gap-y-3">{controls}</div>
        <ReplayButton onClick={onReplay} label={replayLabel} />
      </div>
    </div>
  )
}

// picsum.photos id 599, 800 x 600, inline so the 21st preview needs no image host.
const summit = {
  alt: "A mountain summit rising above a sea of low clouds",
  width: 800,
  height: 600,
  src: "data:image/webp;base64,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",
}

/** Prompt and job line under a generation. Numbers are tabular so the line never jitters. */
function GenerationCaption({
  prompt,
  job,
  className,
}: {
  prompt: string
  job: SimulatedJob
  className?: string
}) {
  const label =
    job.progress === null && job.running
      ? "Queued"
      : job.running
        ? `Step ${job.step} of ${job.total}`
        : "Done"
  return (
    <div className={cn("flex min-w-0 items-baseline justify-between gap-4", className)}>
      <p className="text-[0.8125rem]/[1.25rem] text-(color:--chatcn-fg-muted) min-w-0 truncate">{prompt}</p>
      <span className="text-[0.75rem]/[1rem] text-(color:--chatcn-fg-subtle) shrink-0 tabular-nums">{label}</span>
    </div>
  )
}

const PROMPT = "Mountain summit above a sea of cloud at first light, medium format, quiet palette"

/** The line under each 21st demo that points back to the kit. */
function MoreOn({ slug, children }: { slug: string; children: React.ReactNode }) {
  return (
    <p data-fit-hide className="text-[0.75rem]/[1rem] text-(color:--chatcn-fg-faint) text-center text-balance">
      {children}{" "}
      <a
        href={`https://chatcn.dev/docs/components/${slug}`}
        target="_blank"
        rel="noopener"
        className="text-(color:--chatcn-fg-subtle) hover:text-(color:--chatcn-fg) underline underline-offset-2"
      >
        chatcn.dev
      </a>
    </p>
  )
}

/**
 * A generation resolving out of noise: noise falls and detail rises with each reported diffusion
 * step, reseeding per step. It generates again every few seconds.
 */
export default function DenoiseRevealPreview() {
  const [run, replay] = useRun()
  const job = useSimulatedJob({ total: STEPS, seed: 11 })
  const restart = () => {
    replay()
    job.start()
  }
  useEvery(restart, 8000)
  return (
    <FitFrame>
      <div className="flex w-full flex-col items-center justify-center gap-6 p-6">
        <DemoShell
          className="max-w-lg"
          onReplay={restart}
          replayLabel="Generate again"
          media={
            <DenoiseReveal
              key={run}
              src={summit.src}
              alt={summit.alt}
              progress={job.progress}
              steps={STEPS}
              aspectRatio="4:3"
              className="rounded-(--chatcn-radius-lg) w-full"
            />
          }
          caption={<GenerationCaption prompt={PROMPT} job={job} />}
        />
        <MoreOn slug="denoise-reveal">Driven by your sampler's steps. On</MoreOn>
      </div>
    </FitFrame>
  )
}

More by Aaditya

View all
  • Pixel Orb

    Pixel Orb

    9
  • Dither Orb

    Dither Orb

    9
  • Dot Matrix Loader

    Dot Matrix Loader

    8
  • Halftone Loader

    Halftone Loader

    6
  • ASCII 3D

    ASCII 3D

    5
  • Wireframe Globe

    Wireframe Globe

    5
  • Audio Visualizer

    Audio Visualizer

    5
  • LED Matrix

    LED Matrix

    4

Explore more

Part of chatcn — browse the full library on 21st.dev.