تا بازشدنِ نسخهی عمومی
کاستومایز
عددِ غلتانCounter
عددی که رقمهاش مثلِ اودومتر میغلتند تا به مقدارِ تازه برسن؛ ارقام و جداکنندهها از خودِ Intl فارسی میآن، تغییرها با فنر و پلکانِ پلهای میریزن و رقمهای تندچرخش توی راه بلورِ حرکت میگیرن.
وابستگیها
نوع تعامل
کامپوننت ورودی نمیگیره؛ مقدار رو تو از بیرون عوض میکنی و رقمها میغلتند. دموی زنده چهار صحنه داره: شمارشِ معکوس هر ثانیه میچرخه، داشبورد آمارِ زنده رو بالا و پایین میبره، صحنهی قیمت با سگمنتِ ماهانه/سالانه و دکمههای صندلی میگرده و صحنهی پایه با دکمههای کم/بیشتر/تصادفی مقدار رو جابهجا میکنه. ورودِ هر نمونه هم یه غلتشِ خوشآمد داره که بهمحضِ دیدهشدن بازی میشه.
پراپها
گزینههایی که میتونی به کامپوننت بدی؛ ستارهدارها اجباریاند.
valuenumberپیشفرض: 0عددی که نشان داده میشه؛ هر تغییرش رقمها را میغلتاند.
localestringپیشفرض: 'fa-IR'Locale برای جداکنندهها، نمادها و ارقام؛ پیشفرضِ پورتِ فارسی است و ارقام ۰ تا ۹ را از خودش میگیرد — locale دیگری بده و همان کامپوننت با خطِ رقمِ همان خط میغلتد.
formatIntl.NumberFormatOptionsپیشفرض: —گزینههای قالببندی: ارز، درصد، واحد یا نگارشِ فشرده.
decimalsnumberپیشفرض: —شمارِ ثابتِ رقمِ اعشار؛ نده تا پیشفرضِ قالب بماند.
minDigitsnumberپیشفرض: 1کمینهی رقمِ بخشِ صحیح — صفرهای پیشرویِ عدد.
prefixReactNodeپیشفرض: —محتوای پیش از عدد.
نصب
۱. این آدرس رو یکبار توی components.json بذار تا shadcn مخزن فارسیفای رو بشناسه.
{
"registries": {
"@farsify": "https://farsify.ir/r/{name}.json"
}
}۲. بعد با دستورِ زیر کامپوننت رو نصب کن.
npx shadcn@latest add @farsify/counterپیشنیاز: Tailwind CSS v4 و صفحهٔ راستبهچپ dir="rtl".
نمونه
"use client";
import { useEffect, useState } from "react";
import Counter from "@/components/farsify/counter";
/** ثانیهشمارِ بازگشتی — هر تغییرِ مقدار، رقمها را میغلتاند. */
export function BetaCountdown() {
const [left, setLeft] = useState(2 * 86400 + 14 * 3600 + 37 * 60);
useEffect(() => {
const timer = setInterval(() => setLeft((v) => Math.max(0, v - 1)), 1000);
return () => clearInterval(timer);
}, []);
return (
<Counter
value={left % 60}
minDigits={2}
fontSize={56}
fontWeight={600}
gap={6}
fade={0}
direction="down"
digitStyle={{
padding: "0.18em 0.14em",
borderRadius: "0.18em",
background: "var(--surface-hover)",
}}
/>
);
}
// قالببندی با Intl — ارز، درصد و نگارشِ فشرده، همه با ارقامِ همان locale
<Counter value={48203.17} format={{ style: "currency", currency: "IRR" }} decimals={2} />
<Counter value={0.0342} format={{ style: "percent" }} decimals={2} />
<Counter value={48203} format={{ notation: "compact" }} />
// فنرِ شخصیسازیشده: جهشِ بلند و موجِ پلهای از راستِ عدد
<Counter value={99999} bounce={0.5} stagger={0.12} duration={1.1} />
// خاموشِ بیسروصدا — مناسبِ گوشیِ ضعیف و قابهای ریز
<Counter value={42} motionBlur={false} intro={false} tabular={false} />نکتهها
- ارقامِ فارسی هیچ تبدیلِ دستیای ندارن: از `Intl.NumberFormat` با locale میآن. locale دیگهای بده (عربی، انگلیسی…) و همین کامپوننت با ارقامِ همون خط میغلته.
- برای شمارشِ معکوس، `padding` رو کمی بالا ببر تا رقمها توی کاشی نفس بکشن و `fade: 0` بده تا لبه بریده شه — دموی سایت همین ترکیب رو داره.
- `stagger` شخصیتِ نمایش رو میسازه: صفر یعنی همهی رقمها همزمان بچرخن؛ بالای ۰٫۱ موجِ پلهای از راستِ عدد میریزه.
- روی گوشیِ ضعیف `motionBlur` رو خاموش کن — فیلترِ SVG فقط موقعِ چرخشِ تند فعال میشه، ولی خاموشیاش هزینهای نداره.
- توی `prefers-reduced-motion` چرخشها بیدرنگ مینشینن و مقدارِ تازه بیواسطه نشون داده میشه؛ انیمیشنِ ورود هم کلاً نمیآد.
- این کامپوننت راستبهچپ نمیشه و عمدیه: عدد یه رانِ چپبهراسته. واحد و برچسب رو بیرونِ اون بذار تا توی چیدمانِ فارسی سرِ درست بنشینن.
- `tabular` رو برای ستونهای عددیِ جدولی روشن نگه دار؛ برای نمایشگرِ بزرگِ تکعددی خاموشش کن تا عرض با رقم نرم بره.
مجوز
کد بعد از نصب مالِ خودته؛ هر تغییری خواستی بده و توی پروژهی خودت نگهش دار. برای پروژههای شخصی و تجاری آزاده، حتی اگه کدت بسته باشه. فقط اسم و لینک فارسیفای رو یه جا توی پروژه نگه دار.