پرتوپرتو

DataTable

جدول داده ترکیبی با مرتب‌سازی، صفحه‌بندی، انتخاب ردیف، و حالت‌های بارگذاری و خالی

معرفی

DataTable یک کامپوننت ترکیبی است که جدول، مرتب‌سازی، صفحه‌بندی، انتخاب ردیف، و مدیریت حالت‌های خالی و بارگذاری را در یک API ساده ارائه می‌دهد. این کامپوننت رایج‌ترین الگوی نمایش داده در اپلیکیشن‌های SaaS را پوشش می‌دهد.

چه زمانی استفاده کنیم:

  • لیست داده‌ها با بیش از ۵ آیتم که نیاز به مرتب‌سازی یا صفحه‌بندی دارند
  • جداول با قابلیت انتخاب برای عملیات دسته‌ای
  • هر صفحه لیست در اپلیکیشن (اینفلوئنسرها، کمپین‌ها، گزارش‌ها)

چه زمانی استفاده نکنیم:

  • نمایش ساده ۳-۵ آیتم بدون تعامل — از Table مستقیم استفاده کنید
  • جداول با ساختار بسیار سفارشی — از کامپوننت‌های Table به صورت ترکیبی استفاده کنید
  • نمایش کارتی — از Card استفاده کنید
نامدنبال‌کنندگاننرخ تعامل
علی محمدی۱۲٬۵۰۰۴.۲٪
سارا احمدی۸۷٬۳۰۰۳.۱٪
رضا کریمی۲۳۴٬۰۰۰۲.۸٪
مریم حسینی۵٬۲۰۰۶.۷٪
امیر رضایی۴۵٬۸۰۰۳.۵٪
import { DataTable } from '@parto-system-design/ui'

استفاده پایه

import { DataTable, type DataTableColumn } from '@parto-system-design/ui'

interface Influencer {
  id: number
  name: string
  followers: number
  engagementRate: number
}

const columns: DataTableColumn<Influencer>[] = [
  { id: 'name', header: 'نام', cell: (row) => row.name, sortable: true },
  {
    id: 'followers',
    header: 'فالوورها',
    cell: (row) => row.followers.toLocaleString('fa-IR'),
    sortable: true,
    align: 'end',
  },
  {
    id: 'engagementRate',
    header: 'نرخ تعامل',
    cell: (row) => `${row.engagementRate}٪`,
    sortable: true,
    align: 'end',
  },
]

const data: Influencer[] = [
  { id: 1, name: 'محمد رضایی', followers: 125000, engagementRate: 4.2 },
  { id: 2, name: 'سارا احمدی', followers: 89000, engagementRate: 6.8 },
  { id: 3, name: 'علی محمدی', followers: 350000, engagementRate: 2.1 },
]

<DataTable columns={columns} data={data} />

با مرتب‌سازی

'use client'

import { useState } from 'react'
import { DataTable, type DataTableColumn, type SortDirection } from '@parto-system-design/ui'

function SortableExample() {
  const [sortColumn, setSortColumn] = useState<string | null>(null)
  const [sortDirection, setSortDirection] = useState<SortDirection | null>(null)

  return (
    <DataTable
      columns={columns}
      data={data}
      sort={{
        column: sortColumn,
        direction: sortDirection,
        onSort: (col, dir) => {
          setSortColumn(col)
          setSortDirection(dir)
        },
      }}
    />
  )
}

با صفحه‌بندی

<DataTable
  columns={columns}
  data={pageData}
  pagination={{
    currentPage: 2,
    totalPages: 10,
    onPageChange: (page) => setCurrentPage(page),
  }}
/>

با انتخاب ردیف

'use client'

import { useState } from 'react'

function SelectableExample() {
  const [selected, setSelected] = useState<Set<number>>(new Set())

  return (
    <DataTable
      columns={columns}
      data={data}
      selection={{
        selectedRows: selected,
        onSelectionChange: setSelected,
        getRowKey: (row) => row.id,
      }}
    />
  )
}

حالت بارگذاری

<DataTable columns={columns} data={[]} isLoading loadingRows={5} />

حالت خالی

import { Empty, EmptyIcon, EmptyTitle, EmptyDescription, Button } from '@parto-system-design/ui'
import { SearchX } from 'lucide-react'
;<DataTable
  columns={columns}
  data={[]}
  emptyState={
    <Empty className="border-0">
      <EmptyIcon>
        <SearchX className="size-6" />
      </EmptyIcon>
      <EmptyTitle>اینفلوئنسری یافت نشد</EmptyTitle>
      <EmptyDescription>فیلترهای خود را تغییر دهید یا اینفلوئنسر جدید اضافه کنید</EmptyDescription>
    </Empty>
  }
/>

ترکیب کامل

'use client'

import { useState } from 'react'
import {
  DataTable,
  type DataTableColumn,
  type SortDirection,
  Avatar,
  Badge,
  SocialPlatformBadge,
} from '@parto-system-design/ui'

function FullExample() {
  const [page, setPage] = useState(1)
  const [sortCol, setSortCol] = useState<string | null>(null)
  const [sortDir, setSortDir] = useState<SortDirection | null>(null)
  const [selected, setSelected] = useState<Set<number>>(new Set())

  const columns: DataTableColumn<Influencer>[] = [
    {
      id: 'name',
      header: 'نام',
      sortable: true,
      cell: (row) => (
        <div className="flex items-center gap-2">
          <Avatar src={row.avatar} fallback={row.name[0]} size="sm" />
          <span className="font-medium">{row.name}</span>
        </div>
      ),
    },
    {
      id: 'platform',
      header: 'پلتفرم',
      cell: (row) => <SocialPlatformBadge platform={row.platform} size="sm" />,
    },
    {
      id: 'followers',
      header: 'فالوورها',
      sortable: true,
      align: 'end',
      cell: (row) => row.followers.toLocaleString('fa-IR'),
    },
    {
      id: 'status',
      header: 'وضعیت',
      cell: (row) => (
        <Badge variant={row.active ? 'success' : 'default'} size="sm">
          {row.active ? 'فعال' : 'غیرفعال'}
        </Badge>
      ),
    },
  ]

  return (
    <DataTable
      columns={columns}
      data={influencers}
      size="sm"
      striped
      sort={{
        column: sortCol,
        direction: sortDir,
        onSort: (col, dir) => {
          setSortCol(col)
          setSortDir(dir)
        },
      }}
      selection={{
        selectedRows: selected,
        onSelectionChange: setSelected,
        getRowKey: (row) => row.id,
      }}
      pagination={{
        currentPage: page,
        totalPages: 12,
        onPageChange: setPage,
      }}
      resultCount="۱۴۲ اینفلوئنسر"
    />
  )
}

جدول ویژگی‌ها

DataTable

ویژگینوعپیش‌فرضتوضیح
columnsDataTableColumn<T>[]تعریف ستون‌ها (الزامی)
dataT[]آرایه داده‌ها (الزامی)
size"sm" | "md" | "lg""md"اندازه جدول
isLoadingbooleanfalseنمایش اسکلتون بارگذاری
loadingRowsnumber5تعداد ردیف‌های اسکلتون
emptyStateReactNodeپیام پیش‌فرضمحتوای حالت خالی
paginationDataTablePaginationپیکربندی صفحه‌بندی
sortDataTableSortپیکربندی مرتب‌سازی
selectionDataTableSelection<T>پیکربندی انتخاب ردیف
stripedbooleanfalseردیف‌های راه‌راه
borderedbooleanfalseحاشیه‌دار
stickyHeaderbooleanfalseهدر چسبان
resultCountReactNodeمتن تعداد نتایج
captionstringمتن توضیحی زیر جدول

DataTableColumn

ویژگینوعتوضیح
idstringکلید یکتای ستون
headerReactNodeعنوان ستون
cell(row, index) => ReactNodeتابع رندر سلول
sortablebooleanقابلیت مرتب‌سازی
align"start" | "center" | "end"تراز ستون
classNamestringکلاس اضافی

راهنمای استفاده

بکنید

  • از DataTable برای لیست داده‌ها با بیش از ۵ آیتم که نیاز به مرتب‌سازی یا صفحه‌بندی دارند استفاده کنید - همیشه emptyState سفارشی با پیام فارسی مناسب ارائه دهید - برای جداول با انتخاب ردیف، getRowKey یکتا تعریف کنید

نکنید

  • برای نمایش ساده ۳-۵ آیتم بدون تعامل از DataTable استفاده نکنید — از Table استفاده کنید - ستون‌های غیرضروری اضافه نکنید — اطلاعات باید قابل اسکن باشند - برای نمایش کارتی از جدول استفاده نکنید — از Card در grid layout استفاده کنید

دسترسی‌پذیری

  • ستون‌های قابل مرتب‌سازی از aria-sort استفاده می‌کنند
  • چک‌باکس‌ها دارای aria-label فارسی هستند
  • حالت بارگذاری از اسکلتون بصری استفاده می‌کند
  • ساختار جدول از تگ‌های معنایی HTML (table, thead, tbody, th, td) پیروی می‌کند

تعامل با کیبورد

  • Tab: حرکت بین عناصر تعاملی (چک‌باکس‌ها، دکمه‌های مرتب‌سازی، صفحه‌بندی) - Space: انتخاب ردیف (چک‌باکس) - Enter: فعال‌سازی مرتب‌سازی ستون

کامپوننت‌های مرتبط

  • Table — اگر داده‌های شما ساده هستند و نیاز به مرتب‌سازی یا صفحه‌بندی ندارند، از Table استفاده کنید
  • Card — اگر نمایش کارتی مناسب‌تر از جدول است، از Card در grid layout استفاده کنید