Slot text

Text and numbers that spin into their new value on staggered slot machine reels.

specialtextnumbersnew
Preview
Slot text preview

$1,024

The last reel lands on the new digit as the length changes.

When to use

  • Pricing toggles, KPI cards, dashboards changing period.
  • Launch moments, raffles, and reveals.

When not to use

  • Values that update several times a second.
  • Long sentences; reels are for short values.

shadcn CLI

Also installs (1)

  • manicat-foundation
Manual install(+)
registry.jsonjson
{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "slot-text",
  "type": "registry:ui",
  "title": "Slot text",
  "description": "Text and numbers that spin into their new value on staggered slot machine reels.",
  "categories": [
    "special"
  ],
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "https://manicat.viraza.net/r/manicat-foundation.json"
  ],
  "files": [
    {
      "path": "registry/components/slot-text/slot-text.tsx",
      "type": "registry:component",
      "target": "@components/manicat/slot-text/slot-text.tsx"
    },
    {
      "path": "registry/components/slot-text/slot-text.module.css",
      "type": "registry:component",
      "target": "@components/manicat/slot-text/slot-text.module.css"
    }
  ],
  "docs": "Docs and live preview: https://uiarc.dev/components/slot-text",
  "meta": {
    "tier": "free",
    "kind": "component",
    "docs": "https://manicat.viraza.net/components/slot-text",
    "markdown": "https://uiarc.dev/components/slot-text/markdown",
    "tags": [
      "special",
      "text",
      "numbers",
      "new"
    ]
  }
}

Usage

Install the component, then copy this into your app. Change the content and the props to fit your screen.

example.tsxtsx
"use client";

import { useEffect, useState } from "react";
import { SlotText } from "@/components/manicat/slot-text/slot-text";

const slotAmounts = [1_024, 12_480, 99_200, 736_000];

export function SlotTextExample() {
  const [index, setIndex] = useState(0);

  useEffect(() => {
    const id = setInterval(() => setIndex((current) => (current + 1) % slotAmounts.length), 2000);
    return () => clearInterval(id);
  }, []);

  return (
    <div className="flex w-full flex-col items-center gap-3">
      <p className="text-2xl font-semibold tabular-nums">
        $<SlotText value={slotAmounts[index]} />
      </p>
      <p className="text-xs text-(color:--text-muted)">The last reel lands on the new digit as the length changes.</p>
    </div>
  );
}

Examples

Real screens rather than isolated props. Switch to Code to copy a whole example into your project.

Rolling price Digits spin like a slot machine reel when the amount changes length.

Rolling price Digits spin like a slot machine reel when the amount changes length. preview

$1,024

Accessibility

  • The full value is real text in a visually hidden span; the reels are aria-hidden.
  • announce adds a polite live region for values that change without user action.

Motion

  • Each reel spins with a fast start and a long, soft landing that never passes the target.
  • Reels stop one after another left to right; blur follows each reel's speed, so fast spins smear and landings are sharp.
  • A reel's width follows its new character on a critically damped spring, and new characters grow in while removed ones collapse.
  • Leading symbols such as a currency sign stay on their own reels, and separators stay aligned from the end, so 999 to 1,000 only spins digits.
  • Changing the value mid-spin restarts from the cell on screen, keeping its offset, so nothing jumps.
  • Reduced motion swaps values instantly.

Responsive behavior

  • It is inline text and scales with its font size; reels are measured in em.

Performance

  • Each reel is one transform on a motion value; React re-renders only when the value changes.
  • Blur is removed when a reel is still.

Notes for AI

  • Use it where a change deserves a beat: prices switching plans, stats changing period, a launch status flipping.
  • Put it inside text you style; it inherits font, size, weight, and color. Digits use tabular numerals.
  • For values that tick every second, use a counter with spins={0} or animated-counter; long spins on every tick get tiring.