Skip to content
WANCRAFT

C.104Typography & Text

Falling Text

A sentence whose words or letters break loose and fall with real 2D physics — then can be dragged, thrown and reset.

NewReactCSSTailwindadvanced

Overview

Falling Text keeps a sentence in place until a click, a hover or scrolling into view lets go. Then every word (or letter) becomes a rigid capsule in a small inline physics engine: gravity, bounces off the floor and walls, friction, rotation and collisions between pieces, stepped at a fixed 120 Hz. Fallen pieces can be grabbed and thrown with mouse or touch, and Reset eases everything back into the sentence — via the built-in button, a ref handle or a resetKey prop. Transforms are written straight to the DOM, the loop sleeps once everything rests and pauses offscreen. The sentence stays readable to screen readers throughout, and nothing falls with reduced motion.

01Installation

Method 01 · Registry

CLI verified

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

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

Method 02 · Copy and paste

  1. 1. No extra dependencies — React and Tailwind CSS only.
  2. 2. Copy the source from the Code tab into components/ui/falling-text.tsx.
  3. 3. Import it and adjust props.
Dependencies
None
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 { FallingText } from "@/components/ui/falling-text";

export function FallingTextExample() {
  return (
    <FallingText />
  );
}

03Props

PropTypeDefaultDescription
textstring"Gravity always wins in the end"The sentence; exposed once to assistive technology.
split"words" | "letters""words"Pieces that fall.
trigger"click" | "hover" | "view""click"What drops the sentence (hover becomes tap on touch). The button always works.
gravitynumber1Gravity multiplier (1 ≈ 2400 px/s²).
bouncenumber0.35Restitution from 0 (dead stop) to ~0.8 (very bouncy).
draggablebooleantrueFallen pieces can be dragged and thrown.
heightnumber300Height of the physics box in px.
accentLastbooleantrueDraw the last word in the accent colour.
accentstring"#FF7448"Accent and focus ring colour; deepened on light backgrounds.
showControlbooleantrueShow the Drop / Reset button.
resetKeystring | number—Changing it restores the sentence.
refRef<{ drop(): void; reset(): void }>—Imperative handle.
onFallChange(fallen: boolean) => void—Called when the sentence falls or is reset.
as"p" | "h2" | "h3" | "span""p"Element for the visually hidden sentence.

04Features

  • 01Inline rigid-body physics: gravity, restitution, friction, rotation
  • 02Words as capsules (letters as circles) colliding with each other and the box
  • 03Click, hover (tap on touch) or in-view trigger, plus a Drop / Reset button
  • 04Drag and throw fallen pieces with mouse or touch
  • 05Reset eases every piece back; available as button, ref handle and resetKey prop
  • 06Fixed 120 Hz step, DOM transforms, sleeps at rest and pauses offscreen or in hidden tabs
motion · continuousinput · clickinput · hoverinput · viewportinput · drag

05Accessibility

  • The original sentence is always present as visually hidden text; the physics layer is aria-hidden.
  • The Drop / Reset button is a real, labelled button with a visible focus ring, so the effect is keyboard operable.
  • With prefers-reduced-motion nothing falls: the sentence stays static and the button is not offered.

06Limitations

  • Collision shapes are capsules, so very tall glyphs and descenders can overlap slightly.
  • Collision checks are all-pairs; keep it to a sentence (around 100 pieces), not a paragraph.