Gravity Drop Code
Staggered letters falling down onto a shelf collider with realistic physics bounce.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
"use client";
import { useGSAP } from "@gsap/react";
import gsap from "gsap";
import { useRef, useState } from "react";
gsap.registerPlugin(useGSAP);
export default function AnimationOnePage() {
const containerRef = useRef<HTMLDivElement>(null);
const [textInput, setTextInput] = useState("GRAVITY DROP");
const [triggerKey, setTriggerKey] = useState(0);
useGSAP(
() => {
// Animate the letters falling down
gsap.fromTo(
".falling-letter",
{
y: -400,
rotation: () => gsap.utils.random(-90, 90),
opacity: 0,
scale: 2,
},
{
y: 0,
rotation: 0,
opacity: 1,
scale: 1,
duration: 1.2,
stagger: {
each: 0.08,
from: "random",
},
ease: "bounce.out",
},
);
},
{ scope: containerRef, dependencies: [triggerKey] },
);
const handleReplay = () => {
setTriggerKey((prev) => prev + 1);
};
return (
<div
className="relative min-h-screen bg-[#f0eadf] text-[#2a2a2a] flex flex-col items-center justify-center p-4 selection:bg-wtf-yellow selection:text-black"
ref={containerRef}
>
<div className="absolute inset-0 dot-grid pointer-events-none z-0" />
<div className="z-10 w-full max-w-2xl brutalist-card p-8 bg-white flex flex-col gap-8 text-center relative overflow-hidden">
{/* Header tag */}
<div className="inline-flex self-center items-center gap-2 bg-wtf-orange border-2 border-[#2a2a2a] px-4 py-1.5 rounded-full text-[10px] font-mono font-bold text-white uppercase tracking-widest shadow-[3px_3px_0px_#2a2a2a] tilt-right">
<span>Gravity Drop Sandbox</span>
</div>
{/* Shelf container where text lands */}
<div className="relative min-h-[160px] flex items-center justify-center border-b-4 border-[#2a2a2a] pb-4 bg-zinc-50 rounded-lg shadow-inner">
<div className="absolute top-2 left-2 font-mono text-[9px] text-zinc-400">
SHELF COLLIDER
</div>
<h1 className="text-5xl md:text-7xl font-serif font-black tracking-tight flex flex-wrap justify-center gap-x-2">
{textInput.split(" ").map((word, wordIdx) => (
<span key={wordIdx} className="inline-block whitespace-nowrap">
{word.split("").map((char, charIdx) => (
<span
key={charIdx}
className="falling-letter inline-block transform origin-bottom font-black text-wtf-orange will-change-transform"
style={{ textShadow: "2px 2px 0px #2a2a2a" }}
>
{char}
</span>
))}
</span>
))}
</h1>
</div>
{/* User Controls */}
<div className="flex flex-col md:flex-row gap-4 justify-center items-center">
<input
type="text"
maxLength={20}
value={textInput}
onChange={(e) => setTextInput(e.target.value.toUpperCase())}
placeholder="TYPE TEXT HERE"
className="w-full md:w-64 border-3 border-[#2a2a2a] px-4 py-2.5 font-mono font-bold rounded-lg focus:outline-none focus:bg-yellow-50 placeholder-zinc-400 shadow-[3px_3px_0px_#2a2a2a]"
/>
<div className="flex gap-3 w-full md:w-auto">
<button
onClick={handleReplay}
className="flex-1 md:flex-none brutalist-btn bg-wtf-orange text-white font-mono font-bold text-sm py-3 px-6 rounded-lg uppercase tracking-wider cursor-pointer"
>
☄️ Trigger Drop
</button>
<div className="flex-1 md:flex-none">
<button
onClick={() =>
window.history.length > 1
? window.history.back()
: (window.location.href = "/")
}
className="w-full brutalist-btn bg-wtf-yellow text-[#2a2a2a] font-mono font-bold text-sm py-3 px-6 rounded-lg uppercase tracking-wider cursor-pointer"
>
← Back
</button>
</div>
</div>
</div>
</div>
</div>
);
}
⚙️ Setup & Integration Guide
How to install, import, and configure this animation in your project
Option A: Install via CLI (Recommended)
You can install this component directly into your project via the TweenLabs CLI. It automatically creates the file and configures dependencies:
Option B: Manual Installation
Follow these steps to integrate the component into your project manually:
Install Packages
First, install GSAP and its official React hook helper library (@gsap/react).
Add Required CSS Styles
Copy the styles from the Required CSS tab above, or open the styles.css file that was automatically downloaded with your component. Paste these classes into your global stylesheet (e.g. src/app/globals.css or similar).
Create Component File
Create a new file in your React or Next.js project (e.g. src/components/GravityDrop.tsx) and paste the code from the Standalone React Component tab above. If no standalone tab is available, copy the full page file code and adjust the routing logic for your needs.
Import & Render
Import and render the component in your page or view layout:
import GravityDrop from "@/components/GravityDrop";
export default function Page() {
return (
<main className="min-h-screen p-8 bg-[#f5f5f5] flex items-center justify-center">
<GravityDrop />
</main>
);
}Customization & Component Properties
🛠️ Customization & Component Properties (Props)
You can pass the following settings to configure the layout and animation details:
initialText(string): The text characters to drop and bounce. Defaults to'GRAVITY DROP'.