تا بازشدنِ نسخه‌ی عمومی

ثانیه
دقیقه
ساعت
روز

عددِ غلتانCounter

عددی که رقم‌هاش مثلِ اودومتر می‌غلتند تا به مقدارِ تازه برسن؛ ارقام و جداکننده‌ها از خودِ Intl فارسی می‌آن، تغییرها با فنر و پلکانِ پله‌ای می‌ریزن و رقم‌های تندچرخش توی راه بلورِ حرکت می‌گیرن.

محمدجواد

ساخته شده توسط محمدجواد

سازنده فارسی‌فای، بچه دولوپر

وابستگی‌ها

بدون وابستگی

نوع تعامل

کامپوننت ورودی نمی‌گیره؛ مقدار رو تو از بیرون عوض می‌کنی و رقم‌ها می‌غلتند. دموی زنده چهار صحنه داره: شمارشِ معکوس هر ثانیه می‌چرخه، داشبورد آمارِ زنده رو بالا و پایین می‌بره، صحنه‌ی قیمت با سگمنتِ ماهانه/سالانه و دکمه‌های صندلی می‌گرده و صحنه‌ی پایه با دکمه‌های کم/بیشتر/تصادفی مقدار رو جابه‌جا می‌کنه. ورودِ هر نمونه هم یه غلتشِ خوش‌آمد داره که به‌محضِ دیده‌شدن بازی می‌شه.

پراپ‌ها

گزینه‌هایی که می‌تونی به کامپوننت بدی؛ ستاره‌دارها اجباری‌اند.

value
numberپیش‌فرض: 0

عددی که نشان داده می‌شه؛ هر تغییرش رقم‌ها را می‌غلتاند.

locale
stringپیش‌فرض: 'fa-IR'

Locale برای جداکننده‌ها، نمادها و ارقام؛ پیش‌فرضِ پورتِ فارسی است و ارقام ۰ تا ۹ را از خودش می‌گیرد — locale دیگری بده و همان کامپوننت با خطِ رقمِ همان خط می‌غلتد.

format
Intl.NumberFormatOptionsپیش‌فرض: —

گزینه‌های قالب‌بندی: ارز، درصد، واحد یا نگارشِ فشرده.

decimals
numberپیش‌فرض: —

شمارِ ثابتِ رقمِ اعشار؛ نده تا پیش‌فرضِ قالب بماند.

minDigits
numberپیش‌فرض: 1

کمینه‌ی رقمِ بخشِ صحیح — صفرهای پیش‌رویِ عدد.

prefix
ReactNodeپیش‌فرض: —

محتوای پیش از عدد.

نصب

۱. این آدرس رو یک‌بار توی components.json بذار تا shadcn مخزن فارسی‌فای رو بشناسه.

components.jsonjson
{
  "registries": {
    "@farsify": "https://farsify.ir/r/{name}.json"
  }
}

۲. بعد با دستورِ زیر کامپوننت رو نصب کن.

npx shadcn@latest add @farsify/counter

پیش‌نیاز: Tailwind CSS v4 و صفحهٔ راست‌به‌چپ dir="rtl".

نمونه

counter.tsxtsx
"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` رو برای ستون‌های عددیِ جدولی روشن نگه دار؛ برای نمایشگرِ بزرگِ تک‌عددی خاموشش کن تا عرض با رقم نرم بره.

مجوز

کد بعد از نصب مالِ خودته؛ هر تغییری خواستی بده و توی پروژه‌ی خودت نگهش دار. برای پروژه‌های شخصی و تجاری آزاده، حتی اگه کدت بسته باشه. فقط اسم و لینک فارسی‌فای رو یه جا توی پروژه نگه دار.