نوارِ در حال فکرThought Line

نوارِ «در حال فکر کردن» که مرحله‌ها رو یکی‌یکی می‌گه و آخرش می‌نشینه و آروم می‌شه.

محمدجواد

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

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

وابستگی‌ها

motion

نوع تعامل

خط، مرحله‌ها رو یکی‌یکی نشون می‌ده و روی متنِ جاری یه درخششِ نرم می‌لغزه. با تموم‌شدن، خطِ رنگیِ ریز جلو می‌ره، متن کمی محو می‌شه و رنگِ انجام‌شده می‌گیره. اگه جمع‌شدن روشن باشه، با کلیک جمع و باز می‌شه.

پراپ‌ها

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

label
stringپیش‌فرض: "در حال فکر کردن…"

متنی که وقتی مشغوله نشون داده می‌شه.

doneLabel
string

متنی که بعد از پایان نشون داده می‌شه؛ خالی یعنی همون مرحله‌ی آخر بمونه.

renderLabel
(text, working) => ReactNode

جایگزینیِ کاملِ رندرِ برچسب.

glyph
ThoughtLineGlyphپیش‌فرض: "sparkle"sparkle · dot · none

نشانه‌ی کنارِ متن.

steps
string[]

مرحله‌هایی که به ترتیب نشون داده می‌شن.

collapsible
booleanپیش‌فرض: true

با کلیک جمع و باز شه.

نصب

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

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

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

npx shadcn@latest add @farsify/thought-line

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

نمونه

thought-line.tsxtsx
"use client";

import { useEffect, useState } from "react";
import ThoughtLine from "@/components/farsify/thought-line";

const STEPS = ["خواندنِ پرونده‌ها", "جست‌وجو در مخزن", "نوشتنِ پاسخ"];
const STEP_MS = 900;

export function AssistantStatus() {
  const [visible, setVisible] = useState<string[]>([]);
  const [working, setWorking] = useState(true);

  /*
   * مرحله‌ها باید یکی‌یکی اضافه شوند.
   *
   * خودِ کامپوننت هر گام را تیک‌خورده می‌کشد جز آخری؛ پس اگر هر سه را
   * یک‌جا بدهید، کاربر فقط دو تیکِ آماده و یک خطِ ساکن می‌بیند. وقتی گامِ
   * آخر رسید، working را خاموش کنید تا تیک بخورد و خط بنشیند.
   */
  useEffect(() => {
    const timers = STEPS.map((step, i) =>
      setTimeout(() => {
        setVisible((current) => [...current, step]);
        if (i === STEPS.length - 1) setWorking(false);
      }, i * STEP_MS),
    );
    return () => timers.forEach(clearTimeout);
  }, []);

  return <ThoughtLine steps={visible} working={working} showTimer />;
}

// پایانِ دستی — خودش تمام نمی‌شود تا working را false کنید
<ThoughtLine
  label="در حال آماده‌سازی…"
  doneLabel="آماده شد"
  glyph="dot"
  settleAfter={4}
/>

نکته‌ها

  • مرحله‌ها رو **یکی‌یکی** به فهرست اضافه کن، نه یک‌جا. خودِ کامپوننت هر گام رو تیک‌خورده می‌کشه جز آخری، پس «دونه‌دونه تیک خوردن» فقط وقتی دیده می‌شه که فهرست هم دونه‌دونه پر شه.
  • وقتی گامِ آخر رسید `working` رو خاموش کن — همون لحظه‌ست که گامِ آخر تیک می‌خوره، سر به «زمان فکر:» می‌نشینه و (اگه `collapseOnSettle` روشن باشه) فهرست جمع می‌شه.
  • برای دستیارِ گفت‌وگو عالیه: مرحله‌ها رو از کارِ واقعی پر کن تا کاربر بدونه کجاست.
  • اگه مهلت بدی، خودش بعد از اون مدت تموم می‌شه — برای کارهای کوتاهِ شبیه‌سازی‌شده خوبه.
  • نشانه رو خاموش کن اگه جای دیگه‌ای نشانه داری و نمی‌خوای دوتا شه.
  • `breathDepth` رو بالای ۰٫۶ نبر: کم‌شدگیِ متن از ۱ می‌ره به `1 - depth` و بالاتر از اون خط عملاً ناپدید می‌شه.
  • اگه خودت شمارنده می‌سازی و به `tabular-nums` تکیه می‌کنی: روی ارقامِ **فارسی** کار نمی‌کنه. پیدا براشون گلیفِ متناسب داره. هر رقم رو توی یه گامِ عرض‌ثابت بذار.

مجوز

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