نوار ابزار جدول داده (DataTableToolbar)
دو ابزار جانبی DataTable — Column Visibility dropdown + Export به CSV/TSV
معرفی
دو کامپوننت جانبی برای استفاده در toolbar بالای DataTable. هر دو روی API های موجود DataTable (columnVisibility prop) و export utilityها (CSV/TSV builders) سوار شدهاند.
چه زمانی استفاده کنیم:
- برای جدولهای ستونزیاد که کاربر باید ستونهای نمایشی را خودش انتخاب کند (مانند گزارش کمپین تخفیف فصلی با دهها ستون متریک)
- زمانی که کاربر به خروجی دادهی جدول نیاز دارد — CSV برای Excel یا کپی TSV برای paste در Sheets/Notion
- وقتی میخواهید کنترلهای جدول را در یک نوار ابزار واحد و یکدست بالای
DataTableجمع کنید
چه زمانی استفاده نکنیم:
- برای جدولهای کوچک با ستونهای ثابت و اندک — dropdown مدیریت ستون فقط پیچیدگی اضافه میکند
- برای خروجی PDF یا XLSX — این کامپوننت فقط CSV/TSV تولید میکند؛ از کتابخانهی external با یک
Buttonمعمولی استفاده کنید - وقتی export باید سمت سرور انجام شود —
DataTableExportButtonفقط همانdataسمت کلاینت را serialize میکند؛ در جدولهای server-paged یعنی فقط صفحهی جاری
زمین بازی
با تغییر variant و size، نوار ابزار را بهصورت زنده مشاهده کنید.
استفاده
import { DataTable, DataTableColumnVisibilityToggle, DataTableExportButton } from '@partodata/ui'هر دو کامپوننت controlled و بدون state داخلی هستند: DataTableColumnVisibilityToggle همان object مربوط به columnVisibility را دریافت میکند که به خود DataTable میدهید، و DataTableExportButton همان تعاریف columns و data جدول را (در صورت نیاز با exportValue برای سلولهای React-element). روی صفحهٔ فهرست هر دو propهای قالب ListPage هستند و جدول فرزند آن است: DataTableExportButton در secondaryActions (بدون variant: آنجا default رندر میشود، مثل همهٔ اقدامهای ثانوی) و DataTableColumnVisibilityToggle در toolbarEnd، فقط وقتی محصول انتخاب ستونها را میخواهد (نه در filters). قالب آنها را با بقیهٔ کنترلها همقد میکند (بیرون از صفحه پیشفرضشان xs است). جزئیات API و مثال هر کدام در دو بخش بعدی آمده است.
DataTableColumnVisibilityToggle
Dropdown با checkbox برای روشن/خاموش کردن هر ستون + دکمهی Reset.
import { DataTable, DataTableColumnVisibilityToggle } from '@partodata/ui'
import { ListPage, pageState } from '@partodata/ui/templates'
const [visible, setVisible] = React.useState<Record<string, boolean>>({})
const visibility = { visible, onVisibilityChange: setVisible }
// در صفحهٔ فهرست: در toolbarEnd قالب (کنترل خود فهرست)؛ جدول فرزند ListPage است، بدون size، pagination و حالتهای خودش
;<ListPage
title="اینفلوئنسرها"
toolbarEnd={<DataTableColumnVisibilityToggle columns={columns} visibility={visibility} />}
state={pageState({
data: data?.items,
isLoading,
error,
onRetry: load,
emptyCopy: { title: 'هنوز اینفلوئنسری ثبت نشده است' },
})}
>
<DataTable columns={columns} data={data?.items ?? []} columnVisibility={visibility} />
</ListPage>DataTableExportButton
Dropdown با دو گزینه: Download CSV (فایل با BOM-prefixed UTF-8، مناسب Excel فارسی) و Copy as TSV (کلیپبورد، مناسب paste به Sheets/Notion). از buildCsv / buildTsv / downloadFile helpers هم بهصورت standalone export شدهاند.
import { DataTableExportButton } from '@partodata/ui'
;<DataTableExportButton
filename="comments-2026-04.csv"
data={rows}
columns={[
{ id: 'name', header: 'نام', cell: (r) => r.name, exportValue: (r) => r.name },
{ id: 'sentiment', header: 'احساس', cell: (r) => r.sentiment, exportValue: (r) => r.sentiment },
{ id: 'count', header: 'تعداد', cell: (r) => r.count, exportValue: (r) => r.count },
]}
/>ستونها از همان DataTableColumn معمول استفاده میکنند (id + header + cell). اگر میخواهید مقدار export شده با مقدار رندر تفاوت داشته باشد، exportValue را تعریف کنید — در غیر این صورت cell بهصورت پیشفرض serialize میشود.
برای PDF/Excel xlsx، DS قصد ندارد library سنگین وارد کند — از npm package های external استفاده کنید (xlsx، pdfmake) و آنها را با خود <Button> invoke کنید.
روی صفحهای که با یکی از قالبهای صفحه ساخته شده (هر صفحه)، وقتی data خالی است
(فهرست هنوز بار نشده، نتیجهای نیافته یا خطا داده)، خود قالب دکمه را غیرفعال میکند و دلیلش را میگوید:
aria-disabled (در ترتیب Tab میماند)، کمرنگ، دلیل «خروجی وقتی ممکن است که فهرست دستکم یک ردیف داشته باشد» در
راهنمای ابزار با hover، فوکوس و لمس و بهعنوان توضیح دکمه، و منویش باز نمیشود (دیگر فایل CSV بیردیف دانلود
نمیشود). این در هر جای صفحه است: secondaryActions، actions یک بخش، یا محتوای صفحه. پس خروجی جدول همیشه بی هیچ
شرطی نوشته میشود: نه GatedAction روی تعداد ردیفها، نه disabled، نه rows.length > 0 && … (قاعدهٔ ESLint
parto/page-primary-action هر سه را نشان میدهد). وقتی ردیفها میرسند همان دکمه فعال میشود و فوکوس رویش میماند.
بیرون از قالب صفحه (مثلاً در نمونههای مستقل همین صفحه) دکمه روی ردیفهایش بسته نمیشود.
propهای دیگر دکمه (و ref) همانطور که هستند به دکمهٔ trigger میرسند؛ disabled جزو آنها نیست. خروجیای که کاربر
اجازهاش را ندارد (یا سهمیهاش تمام شده) فرزند GatedAction میشود: همان دکمه
aria-disabled با دلیل همان GatedAction است و منویش با کلیک، Enter یا پیکان پایین باز نمیشود:
<GatedAction allowed={canExport} reason="خروجی گرفتن فقط برای اعضای فضای کار ممکن است">
<DataTableExportButton columns={columns} data={rows} filename="mentions.csv" label="خروجی CSV" />
</GatedAction>راهنمای استفاده
بکنید
- روی صفحهٔ فهرست
DataTableExportButtonرا درsecondaryActionsوDataTableColumnVisibilityToggleرا درtoolbarEndقالبListPageبگذارید، بدونvariant، نه در یکdivباflexکه خودتان میسازید - برای محتوای فارسی، CSV با BOM-UTF8 prefix را Excel درست باز میکند — این کامپوننت پیشفرض همین کار را میکند - برای دادهی بزرگ، در کلیک export یکToastبا progress نمایش دهید — کاربر هیچ feedback ندارد
نکنید
- PDF/XLSX را در lib bundle نکنید — تخصصی است و سنگین — بهصورت optional dep در consumer install کنید - در
ExportButton مقدار خام
accessorبا کاما/نقل قول را escape کنید —buildCsvوbuildTsvاین کار را خودکار انجام میدهند؛ فقط همین helperهای عمومی (buildCsv/buildTsv/downloadFile) export شدهاند، پس منطق escape را دور نزنید
جدول ویژگیها
DataTableColumnVisibilityToggle
DataTableExportButton
Helperهای standalone
buildCsv(columns, data) → string— تولید CSV با escape مناسب (کاما، نقل قول، newline)buildTsv(columns, data) → string— تولید TSV (tab-separated)downloadFile(filename, content, mime?)— trigger دانلود مرورگر با BOM برای UTF-8
دسترسیپذیری
- هر دو روی Radix
DropdownMenuساخته شدهاند — open/close با Enter/Space روی trigger، navigation با Arrow keys، Escape برای close. - آیکونهای
Settings2وDownloadباaria-hidden="true"رندر میشوند؛ متن دکمه (labelیا locale-aware fallback) مسئول a11y است. DropdownMenuCheckboxItemدر ColumnVisibilityToggle خودrole="menuitemcheckbox"وaria-checkedمعنادار را تأمین میکند.- پس از انتخاب CSV/TSV، menu بسته میشود ولی هیچ live announcement خودکار نیست؛ برای دادهی بزرگ یک
Toastبا feedback نمایش دهید (به راهنمای استفاده مراجعه کنید). - خروجی بیردیف، و خروجیای که درون
GatedActionبسته شده،aria-disabledاست (در ترتیب Tab میماند و دلیلش را بهعنوان توضیح میخواند) و منویی باز نمیکند؛ وقتی در دسترس میشود همان دکمه میماند و فوکوس از آن نمیرود. - در RTL،
align="end"رویDropdownMenuContentبه سمت start منطقی align میشود — physical right/left استفاده نشده.
کامپوننتهای مرتبط
- خود جدول → DataTable
- مقایسهی ردیفهای انتخابشده → TableComparisonView
- سلولهای inline (sparkline، trend، sentiment) → DataTableCells (در manifest)