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 | غیرفعال |
<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-table | wrapper اصلی |
data-fara-table-search-input | input جستجوی سراسری |
data-fara-table-loading-overlay | overlay حالت loading |
data-fara-table-table | عنصر <table> |
data-fara-table-head / data-fara-table-body | head و body جدول |
data-fara-table-header-cell | هر سلول سرستون |
data-fara-table-sort-icon | آیکون مرتبسازی؛ دارای data-active هنگام فعال بودن |
data-fara-table-filter | wrapper فیلتر ستون |
data-fara-table-filter-button | دکمهی بازکردن فیلتر؛ دارای data-active |
data-fara-table-filter-popover | پنل فیلتر که در Portal رندر میشود |
data-fara-table-filter-input | input فیلتر |
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-pagination | wrapper صفحهبندی |
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
| Prop | Type | Default | Description |
|---|---|---|---|
columns | TableColumn<T>[] | - | تعریف ستونها (الزامی) |
data | T[] | - | دادهی جدول (الزامی) |
rowKey | (row: T) => string | - | کلید یکتای هر سطر (الزامی) |
emptyMessage | string | «دادهای برای نمایش وجود ندارد» | پیام حالت خالی |
loading | boolean | false | نمایش overlay بارگذاری |
maxHeight | string | - | ارتفاع حداکثر با سرستون sticky |
className | string | - | کلاس CSS اضافی برای سفارشیسازی |
sorting | SortingConfig | {} | تنظیمات مرتبسازی |
filtering | FilteringConfig | {} | تنظیمات فیلتر ستونی |
globalSearch | GlobalSearchConfig | {} | تنظیمات جستجوی سراسری |
pagination | PaginationConfig | {} | تنظیمات صفحهبندی |
selection | SelectionConfig<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;
}