پرش به مطلب اصلی

Table

کامپوننت Table برای نمایش داده‌های جدولی استفاده می‌شود. یک جدول ساده فقط columns و data می‌خواهد، اما هر قابلیت اضافه — جستجو، فیلتر، مرتب‌سازی، صفحه‌بندی و انتخاب سطر — با یک شیء config جداگانه فعال می‌شود و می‌تواند در سمت client یا server کار کند.

Import​

import { Table } from "fara-ui";

اگر هنوز FaraUI را نصب و راه‌اندازی نکرده‌ای، ابتدا صفحه‌ی شروع به کار را ببین.

Basic Usage​

<Table
columns={[
{ key: "name", header: "نام" },
{ key: "role", header: "نقش" },
]}
data={users}
rowKey={(row) => row.id}
/>;

Playground​

این دمو جستجوی سراسری، فیلتر ستون، مرتب‌سازی و صفحه‌بندی را هم‌زمان در حالت client فعال دارد — امتحانش کن:

نقشوضعیت
سارا محمدیمدیر34فعال
علی رضاییتوسعه‌دهنده28فعال
مریم کریمیطراح31غیرفعال
نمایش 1-3 از 5
1 / 2
<Table
columns={[
{ key: "name", header: "نام", sortable: true, filterable: true },
{ key: "role", header: "نقش", filterable: true },
{ key: "age", header: "سن", sortable: true },
{ key: "status", header: "وضعیت" },
]}
data={users}
rowKey={(row) => row.id}
sorting={{ enabled: true, mode: "client" }}
filtering={{ enabled: true, mode: "client" }}
globalSearch={{ enabled: true, mode: "client" }}
pagination={{ enabled: true, mode: "client", pageSize: 3 }}
/>

Columns​

هر ستون از نوع TableColumn<T> است:

  • key (الزامی) — شناسه‌ی ستون؛ به‌صورت پیش‌فرض برای خواندن مقدار، از این فیلد روی سطر استفاده می‌شود
  • header (الزامی) — متن سرستون
  • accessor — تابع سفارشی برای استخراج مقدار (برای مرتب‌سازی/فیلتر/جستجو)
  • render — رندر سفارشی سلول؛ مثلاً نمایش Badge برای وضعیت. اگر پاس نشود، مقدار خام فیلد نمایش داده می‌شود
  • sortable / filterable — این ستون در مرتب‌سازی/فیلتر شرکت می‌کند

Client or Server?​

هر قابلیت یک config با دو کلید مهم دارد:

  • enabled (پیش‌فرض false) — فعال‌سازی قابلیت
  • mode (پیش‌فرض "server") — محل انجام کار

مهم: اگر فقط enabled: true بدهی، حالت server در نظر گرفته می‌شود؛ یعنی جدول فقط «قصد» کاربر را از طریق callback به تو گزارش می‌دهد و خودش هیچ کاری با داده انجام نمی‌دهد. برای اینکه جدول خودش مرتب/فیلتر/صفحه‌بندی کند، حتماً mode: "client" را صریح بنویس.

در حالت server، داده‌ی پاس‌شده به data همان‌طور که هست رندر می‌شود و تو مسئولی که با توجه به state های گزارش‌شده (مثلاً از API جدید بگیری و data را به‌روز کنی).

Features​

Global Search - globalSearch​

globalSearch={{
enabled: true,
mode: "client",
placeholder: "جستجو در همه‌ی ستون‌ها...",
}}

در حالت client، جستجو روی مقادیر همه‌ی ستون‌ها انجام می‌شود. در حالت server مقدار جستجو با onChange گزارش می‌شود.

Sorting - sorting​

sorting={{ enabled: true, mode: "client" }} // state داخلی
// یا
sorting={{
enabled: true,
state: { key: "name", direction: "asc" }, // state از بیرون
onChange: (state) => fetchPage(state),
}}

مرتب‌سازی با کلیک روی سرستون‌های sortable بین سه حالت asc → desc → بدون مرتب‌سازی چرخیده می‌شود. مقایسه‌ی متن‌ها با localeCompare(..., "fa") انجام می‌شود تا ترتیب فارسی درست باشد.

Column Filtering - filtering​

filtering={{ enabled: true, mode: "client" }}

با کلیک روی آیکون فیلتر سرستون‌های filterable، یک input متنی باز می‌شود. در حالت client، مقدار واردشده با includes و بدون حساسیت به بزرگی/کوچکی حروف روی مقدار همان ستون اعمال می‌شود. در حالت server فیلترهای فعال با onChange به‌صورت Record<string, string> گزارش می‌شوند:

filtering={{
enabled: true,
mode: "server",
state: { role: "توسعه" },
onChange: (filters) => fetchUsers({ filters }),
}}

Pagination - pagination​

pagination={{
enabled: true,
mode: "client",
pageSize: 10,
pageSizeOptions: [10, 25, 50],
}}
  • در حالت client، جدول خودش صفحه‌بندی می‌کند؛ totalItems خودکار از data محاسبه می‌شود.
  • در حالت server، تعداد کل آیتم‌ها را با totalItems بده و onPageChange/onPageSizeChange را گوش بده.

Row Selection - selection​

selection={{
enabled: true,
onChange: (keys, rows) => console.log(keys, rows),
}}

ستون چک‌باکس اضافه می‌شود (شامل «انتخاب همه» با حالت indeterminate). در حالت client، کلیدهای انتخاب‌شده با onChange گزارش می‌شوند؛ برای کنترل از بیرون selectedKeys را پاس بده.

Other States​

  • loading — یک overlay با Spinner روی جدول نمایش می‌دهد؛ مناسب رفرش داده
  • maxHeight — ارتفاع حداکثر کانتینر جدول (مثل "400px")؛ سرستون sticky می‌شود
  • emptyMessage — پیام حالت خالی (پیش‌فرض «داده‌ای برای نمایش وجود ندارد»)

Data Attributes and Customize CSS​

Table برای ریشه، ابزارها، جدول، سطرها و کنترل‌های قابلیت‌ها hookهای پایدار ارائه می‌کند:

Attributeکاربرد
data-fara-tablewrapper اصلی
data-fara-table-search-inputinput جستجوی سراسری
data-fara-table-loading-overlayoverlay حالت loading
data-fara-table-tableعنصر <table>
data-fara-table-head / data-fara-table-bodyhead و body جدول
data-fara-table-header-cellهر سلول سرستون
data-fara-table-sort-iconآیکون مرتب‌سازی؛ دارای data-active هنگام فعال بودن
data-fara-table-filterwrapper فیلتر ستون
data-fara-table-filter-buttonدکمه‌ی بازکردن فیلتر؛ دارای data-active
data-fara-table-filter-popoverپنل فیلتر که در Portal رندر می‌شود
data-fara-table-filter-inputinput فیلتر
data-fara-table-checkbox-cell / data-fara-table-checkboxسلول و checkbox انتخاب
data-fara-table-rowهر سطر؛ دارای data-selected
data-fara-table-cellهر سلول داده
data-fara-table-emptyسلول حالت خالی
data-fara-table-paginationwrapper صفحه‌بندی
data-fara-table-pagination-infoمتن بازه‌ی آیتم‌ها
data-fara-table-pagination-controlsکنترل‌های صفحه‌بندی
data-fara-table-page-size-selectانتخاب تعداد آیتم در صفحه
data-fara-table-pagination-buttonدکمه‌ی قبلی/بعدی
data-fara-table-pagination-currentصفحه‌ی فعلی و تعداد صفحات
<Table className="users-table" columns={columns} data={users} rowKey={(row) => row.id} />
[data-fara-table] {
font-size: 0.9375rem;
}

[data-fara-table-row][data-selected] {
background: #eff6ff;
}

[data-fara-table-sort-icon][data-active] {
color: #2563eb;
}

[data-fara-table-loading-overlay] {
backdrop-filter: blur(2px);
}

[data-fara-table-filter-popover] {
z-index: 20;
}

پنل فیلتر با Portal در document.body رندر می‌شود؛ selector آن را به wrapper جدول وابسته نکن. className روی wrapper اصلی data-fara-table اعمال می‌شود.

Accessibility and Current Limitations​

  • Table از عنصر native <table> استفاده می‌کند؛ برای هر ستون header واضح و برای selection از rowKey پایدار استفاده کن.
  • checkbox انتخاب همه و checkbox هر ردیف aria-label فارسی دارند.
  • input جستجو و فیلتر را با label یا متن راهنما در اطراف جدول توضیح بده.
  • در پیاده‌سازی فعلی، عنوان sortable با span کلیک‌پذیر ساخته می‌شود و دکمه‌ی keyboard مستقل ندارد؛ اگر مرتب‌سازی کامل با کیبورد لازم است، این محدودیت را با wrapper سفارشی یا بهبود خود کامپوننت پوشش بده.

Feature Processing Order​

داده‌ها به این ترتیب از فیلترها عبور می‌کنند — در حالت server هر مرحله pass-through است:

globalSearch → filtering → sorting → pagination → selection

Props​

PropTypeDefaultDescription
columnsTableColumn<T>[]-تعریف ستون‌ها (الزامی)
dataT[]-داده‌ی جدول (الزامی)
rowKey(row: T) => string-کلید یکتای هر سطر (الزامی)
emptyMessagestring«داده‌ای برای نمایش وجود ندارد»پیام حالت خالی
loadingbooleanfalseنمایش overlay بارگذاری
maxHeightstring-ارتفاع حداکثر با سرستون sticky
classNamestring-کلاس CSS اضافی برای سفارشی‌سازی
sortingSortingConfig{}تنظیمات مرتب‌سازی
filteringFilteringConfig{}تنظیمات فیلتر ستونی
globalSearchGlobalSearchConfig{}تنظیمات جستجوی سراسری
paginationPaginationConfig{}تنظیمات صفحه‌بندی
selectionSelectionConfig<T>{}تنظیمات انتخاب سطر
interface TableColumn<T> {
key: string; // الزامی
header: string; // الزامی
render?: (row: T) => ReactNode;
accessor?: (row: T) => string | number;
sortable?: boolean;
filterable?: boolean;
}

// الگوی مشترک همه‌ی config ها:
interface SortingConfig {
enabled?: boolean; // پیش‌فرض false
mode?: "server" | "client"; // پیش‌فرض "server"
state?: SortState;
onChange?: (state: SortState) => void;
}

interface SortState {
key: string | null;
direction: "asc" | "desc" | null;
}