Slot-machine Letters
Installation
npx shadcn@latest add https://uibrik.com/r/slot-letters.jsonInstall the packages
npm install motionAdd the cn helper
Imports
cnfrom@/lib/utils, whichshadcn initcreates. Add it by hand without shadcn.Copy the source into your project
components/uibrik/slot-letters/slot-letters.tsx"use client"; import { cn } from "@/lib/utils"; import { motion } from "motion/react"; import { EASE_OUT, TEXT, pick, type EffectProps } from "../_text-effects/shared"; // 10 — Letters roll on vertical reels like an odometer and stop on the next // word, each reel a beat after the one before it. const REEL = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const ODOMETER_WORDS = ["ROUND", "ABOUT", "TURNS", "AGAIN"]; export function SlotLetters({ play, words = ODOMETER_WORDS, duration = 0.5, stagger = 0.05, }: EffectProps & { /** Uppercase A–Z words; each letter rolls on its own reel. */ words?: string[]; /** Seconds for a reel to stop. */ duration?: number; /** Seconds between reels. */ stagger?: number; }) { const word = pick(words, play); return ( <p aria-label={word} className={cn(TEXT, "flex leading-none")}> {Array.from(word).map((ch, i) => ( <span key={i} aria-hidden className="relative h-[1.2em] overflow-hidden"> <motion.span className="flex flex-col" initial={false} animate={{ y: `${-REEL.indexOf(ch) * 1.2}em` }} transition={{ duration, delay: i * stagger, ease: EASE_OUT }} > {Array.from(REEL).map((r) => ( <span key={r} className="flex h-[1.2em] items-center justify-center"> {r} </span> ))} </motion.span> </span> ))} </p> ); }
Adds the files to
components/uibrik/slot-letters and installs motion. With the @uibrik namespace set up: npx shadcn@latest add @uibrik/slot-letters.Props
SlotLetters- words
- Type string[]
- ["ROUND","ABOUT","TURNS","AGAIN"]
- Uppercase A–Z words, cycled one per play.
- duration
- Type number
- 0.5
- Time for a reel to stop.
- stagger
- Type number
- 0.05
- Delay between reels.
- playrequired
- Type number
- –
- Each change plays the effect again; 0 shows its resting state.