Slot text
Text and numbers that spin into their new value on staggered slot machine reels.
specialtextnumbersnew
Preview
Slot text preview
Live · keyboard ready
$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
Live · keyboard ready
$1,024
rolling-price-digits-spin-like-a-slot-machine-reel-when-the-amount-changes-length-.tsxtsx
"use client";
import { useEffect, useState } from "react";
import { SlotText } from "@/components/manicat/slot-text/slot-text";
const prices = [1_024, 12_480, 99_200, 736_000];
export function SlotTextPriceExample() {
const [index, setIndex] = useState(0);
useEffect(() => {
const id = setInterval(() => setIndex((current) => (current + 1) % prices.length), 2000);
return () => clearInterval(id);
}, []);
return (
<p className="text-3xl font-semibold tabular-nums">
$<SlotText value={prices[index]} />
</p>
);
}
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.