Skip to content
WANCRAFT

C.191Typography & Text

Text Image Reveal

Editorial text where marked words reveal an image: an inline pill that pushes the line apart, or a floating print that follows the pointer.

NewReactMotionTailwindintermediate

Overview

Text Image Reveal turns a few words in a paragraph into small windows. In inline mode the word grows a pill-shaped thumbnail right inside the line, and the spring-driven width pushes the rest of the sentence aside. In float mode a larger image springs in near the pointer, tracks it on a spring and leans with its horizontal speed, settling at a slight tilt. You mark words with <TextImageReveal.Word image alt>, and each one is a real button: hover reveals it with a mouse, keyboard focus reveals it straight away, a tap toggles it on touch screens, and Escape hides it. The image's description reaches assistive tech through aria-describedby, while the image itself stays decorative. With reduced motion the image appears and disappears instantly and stays anchored above its word.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/text-image-reveal.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/text-image-reveal.json

Method 02 · Copy and paste

  1. 1. Install the dependencies below.
  2. 2. Copy the source from the Code tab into components/ui/text-image-reveal.tsx.
  3. 3. Import it and adjust props.
npm install motion
Dependencies
motion
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { TextImageReveal } from "@/components/ui/text-image-reveal";

export function TextImageRevealExample() {
  return (
    <TextImageReveal>
      <p className="text-3xl font-medium tracking-tight">
        We traded the{" "}
        <TextImageReveal.Word image="/harbour.jpg" alt="A sailboat in a harbour at sunset">
          harbour
        </TextImageReveal.Word>{" "}
        for the city.
      </p>
    </TextImageReveal>
  );
}

03Props

PropTypeDefaultDescription
childrenReactNode—Required. Running text containing <TextImageReveal.Word> elements.
mode"inline" | "float""inline"Inline pill inside the line, or a floating image near the pointer / word.
pillWidthnumber2.4Inline pill width in em.
floatWidthnumber200Floating image width in px (4:3).
tiltnumber8Maximum lean / entry rotation of the floating image, in degrees.
followPointerbooleantrueFloat mode: follow the mouse rather than anchoring above the word.
spring{ stiffness: number; damping: number; mass: number }{ stiffness: 320, damping: 28, mass: 0.7 }Spring for the pill width and floating image.
cue"underline" | "dotted" | "highlight""underline"How revealable words are marked.
accentstring"#FF7448"Cue and focus ring colour.
Word: image / altstring / string—Required on <TextImageReveal.Word> (also exported as TextImageRevealWord): image URL and its description.

04Features

  • 01Inline mode: a pill-shaped thumbnail grows inside the line on a spring and pushes the text apart
  • 02Float mode: a 4:3 print springs in near the pointer, follows it and leans with its horizontal velocity
  • 03Compound API: <TextImageReveal.Word image alt> anywhere inside the text, any number of times
  • 04Mouse hover, keyboard focus and touch tap all reveal; Escape hides
  • 05Pointer tracking writes motion values only — no React renders on pointer move
motion · springinput · hoverinput · pointerinput · focusinput · keyboardinput · click

05Accessibility

  • Each marked word is a native <button> with aria-expanded and aria-describedby pointing at its image description ("Image: …").
  • Keyboard focus reveals the image immediately; Enter / Space toggles it; Escape hides it (consumed only while it is showing); blur hides it.
  • On touch screens a tap toggles the image and a tap anywhere else closes it — nothing depends on hover.
  • The image itself is decorative (alt="" inside an aria-hidden layer) because its description is already announced.
  • prefers-reduced-motion: images appear and disappear instantly, with no spring, tilt or pointer tracking.

06Limitations

  • A marked word renders as a button, so it does not break across lines; keep marked phrases short.
  • Float mode positions the image inside the TextImageReveal root, which therefore must not clip its overflow.