HextaUI

Table

Yüzey stili, sarmalayan veya kompakt hücreler, yapışkan başlıklar, sabitlenmiş sütunlar ve kaydırma ipuçları olan duyarlı bir tablo.

InvoiceClientStatusAmount
INV-0418NorthwindPaid$2,400.00
INV-0419GlobexPending$860.00
INV-0420InitechPaid$1,320.50
INV-0421UmbrellaOverdue$415.00
Total$4,995.50
import { Badge, BadgeDot } from "@/components/ui/badge"
import {
  Table,
  TableBody,
  TableCell,
  TableFooter,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const invoices = [
  { id: "INV-0418", client: "Northwind", status: "Paid", amount: 2400 },
  { id: "INV-0419", client: "Globex", status: "Pending", amount: 860 },
  { id: "INV-0420", client: "Initech", status: "Paid", amount: 1320.5 },
  { id: "INV-0421", client: "Umbrella", status: "Overdue", amount: 415 },
]

const currency = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
})

const tones = {
  Paid: "success",
  Pending: "info",
  Overdue: "destructive",
} as const

export function TableDemo() {
  const total = invoices.reduce((sum, invoice) => sum + invoice.amount, 0)

  return (
    <Table variant="surface" className="min-w-md">
      <TableHeader>
        <TableRow>
          <TableHead>Invoice</TableHead>
          <TableHead>Client</TableHead>
          <TableHead>Status</TableHead>
          <TableHead align="end">Amount</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {invoices.map((invoice) => (
          <TableRow key={invoice.id}>
            <TableHead scope="row">{invoice.id}</TableHead>
            <TableCell>{invoice.client}</TableCell>
            <TableCell>
              <Badge variant={tones[invoice.status as keyof typeof tones]}>
                <BadgeDot />
                {invoice.status}
              </Badge>
            </TableCell>
            <TableCell align="end">{currency.format(invoice.amount)}</TableCell>
          </TableRow>
        ))}
      </TableBody>
      <TableFooter>
        <TableRow>
          <TableCell colSpan={3}>Total</TableCell>
          <TableCell align="end">{currency.format(total)}</TableCell>
        </TableRow>
      </TableFooter>
    </Table>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/table.json

Bileşeni, HextaUI tema token'larını ve bileşenin bağımlı olduğu tüm HextaUI bileşenlerini ekler.

import {
  Table,
  TableBody,
  TableCaption,
  TableCell,
  TableFooter,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
<Table variant="surface">
  <TableHeader>
    <TableRow>
      <TableHead>Invoice</TableHead>
      <TableHead align="end">Amount</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableHead scope="row">INV-0418</TableHead>
      <TableCell align="end">$2,400.00</TableCell>
    </TableRow>
  </TableBody>
</Table>

Her satırı adlandıran hücre için <TableHead scope="row"> kullanın. Ekran okuyuculara satırın başlığı olarak okunur ve daha güçlü bir metin rengi alır. Sıralama, filtreleme ve seçim için <DataTable /> üzerine kurun.

Table
├── TableCaption
├── TableHeader
│   └── TableRow
│       └── TableHead
├── TableBody
│   └── TableRow
│       └── TableCell
└── TableFooter
    └── TableRow
        └── TableCell

Varsayılan

Varsayılan varyantın yüzeyi yoktur, yalnızca satırlar arasında ince çizgiler vardır; bir kart veya sayfa bölümü içinde duran tablolar için. <TableCaption /> altındaki tabloyu tanımlar.

import {
  Table,
  TableBody,
  TableCaption,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const releases = [
  { version: "2.4.0", date: "Oct 2, 2026", changes: 18 },
  { version: "2.3.1", date: "Sep 21, 2026", changes: 4 },
  { version: "2.3.0", date: "Sep 12, 2026", changes: 23 },
]

export function TablePlain() {
  return (
    <Table>
      <TableCaption>Recent releases.</TableCaption>
      <TableHeader>
        <TableRow>
          <TableHead>Version</TableHead>
          <TableHead>Released</TableHead>
          <TableHead align="end">Changes</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {releases.map((release) => (
          <TableRow key={release.version}>
            <TableHead scope="row">{release.version}</TableHead>
            <TableCell>{release.date}</TableCell>
            <TableCell align="end">{release.changes}</TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  )
}

Kompakt

size="sm" yoğun veri için satır yüksekliğini ve dolguyu sıkılaştırır.

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const rows = [
  { region: "us-east-1", latency: "42 ms", uptime: "99.99%" },
  { region: "eu-west-2", latency: "38 ms", uptime: "99.98%" },
  { region: "ap-south-1", latency: "71 ms", uptime: "99.95%" },
]

export function TableSizes() {
  return (
    <Table variant="surface" size="sm">
      <TableHeader>
        <TableRow>
          <TableHead>Region</TableHead>
          <TableHead align="end">Latency</TableHead>
          <TableHead align="end">Uptime</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map((row) => (
          <TableRow key={row.region}>
            <TableCell>
              <span className="font-mono text-xs">{row.region}</span>
            </TableCell>
            <TableCell align="end">{row.latency}</TableCell>
            <TableCell align="end">{row.uptime}</TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  )
}

Metni sarma

Hücreler varsayılan olarak tek satırda kalır; bu veriye uygundur. wrap sarmalarına izin verir ve satırları üste hizalar; sözlükler veya API başvuruları gibi düz yazı için. table-fixed ve sütun genişlikleriyle birlikte kullanın.

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const terms = [
  {
    term: "Concentric radius",
    meaning:
      "An inner corner radius equal to the outer radius minus the gap between the two edges, so nested shapes look like they belong together.",
  },
  {
    term: "Hairline",
    meaning:
      "The thinnest line the screen can draw: 1px on standard displays and two thirds of a pixel on high-density ones.",
  },
]

export function TableWrap() {
  return (
    <Table variant="surface" wrap className="table-fixed">
      <TableHeader>
        <TableRow>
          <TableHead className="w-1/3">Term</TableHead>
          <TableHead>Meaning</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {terms.map((row) => (
          <TableRow key={row.term}>
            <TableHead scope="row">{row.term}</TableHead>
            <TableCell>
              <span className="text-muted-foreground">{row.meaning}</span>
            </TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  )
}

Geniş tablolar

Kapsayıcısından geniş tablolar yana kayar. Yumuşak solmalar her iki yanda daha fazlası olduğunu gösterir ve klavye kullanıcıları ok tuşlarıyla kaydırabilsin diye kaydırma alanı odaklanabilir olur. Solmaları scrollFade={false} ile kapatın.

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const months = [
  "Jan",
  "Feb",
  "Mar",
  "Apr",
  "May",
  "Jun",
  "Jul",
  "Aug",
  "Sep",
  "Oct",
  "Nov",
  "Dec",
]

const series = [
  {
    name: "Visitors",
    values: [
      812, 904, 1021, 990, 1203, 1340, 1288, 1410, 1502, 1622, 1590, 1711,
    ],
  },
  {
    name: "Sign-ups",
    values: [41, 52, 66, 59, 71, 83, 80, 92, 97, 110, 104, 121],
  },
]

export function TableScroll() {
  return (
    <Table variant="surface" className="w-max min-w-full">
      <TableHeader>
        <TableRow>
          <TableHead>Metric</TableHead>
          {months.map((month) => (
            <TableHead key={month} align="end">
              {month}
            </TableHead>
          ))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {series.map((row) => (
          <TableRow key={row.name}>
            <TableHead scope="row">{row.name}</TableHead>
            {row.values.map((value, index) => (
              <TableCell key={months[index]} align="end">
                {value.toLocaleString("en-US")}
              </TableCell>
            ))}
          </TableRow>
        ))}
      </TableBody>
    </Table>
  )
}

Sabitlenmiş sütun

pinned="start" geri kalan kayarken ilk sütunu görünümde tutar; pinnedEdge içerik altına kayınca bir gölge gösterir.

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const quarters = [
  "Q1 2025",
  "Q2 2025",
  "Q3 2025",
  "Q4 2025",
  "Q1 2026",
  "Q2 2026",
  "Q3 2026",
]

const teams = [
  { name: "Design systems", values: [12, 14, 15, 18, 21, 22, 24] },
  { name: "Platform", values: [31, 30, 33, 35, 34, 38, 40] },
  { name: "Growth", values: [8, 9, 11, 10, 12, 15, 16] },
]

export function TablePinned() {
  return (
    <Table variant="surface" className="w-max min-w-full">
      <TableHeader>
        <TableRow>
          <TableHead pinned="start" pinnedEdge>
            Team
          </TableHead>
          {quarters.map((quarter) => (
            <TableHead key={quarter} align="end">
              {quarter}
            </TableHead>
          ))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {teams.map((team) => (
          <TableRow key={team.name}>
            <TableHead scope="row" pinned="start" pinnedEdge>
              {team.name}
            </TableHead>
            {team.values.map((value, index) => (
              <TableCell key={quarters[index]} align="end">
                {value}
              </TableCell>
            ))}
          </TableRow>
        ))}
      </TableBody>
    </Table>
  )
}

stickyHeader yüksekliği sınırlı bir tabloda başlığı görünümde tutar ve satırlar altında kaymaya başlayınca altına ince bir çizgi ekler.

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const events = Array.from({ length: 24 }, (_, index) => ({
  id: `evt_${(1024 + index).toString(16)}`,
  type: ["deploy", "rollback", "scale", "restart"][index % 4],
  minutes: index * 7 + 2,
}))

export function TableSticky() {
  return (
    <Table variant="surface" stickyHeader containerClassName="max-h-72">
      <TableHeader>
        <TableRow>
          <TableHead>Event</TableHead>
          <TableHead>Type</TableHead>
          <TableHead align="end">When</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {events.map((event) => (
          <TableRow key={event.id}>
            <TableCell>
              <span className="font-mono text-xs">{event.id}</span>
            </TableCell>
            <TableCell>{event.type}</TableCell>
            <TableCell align="end">{event.minutes} min ago</TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  )
}

Sağdan sola

Hizalama, sabitlenmiş sütunlar ve kaydırma solmaları okuma yönünü izler.

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const rows = [
  { name: "التصميم", members: 8, budget: "١٢٬٠٠٠" },
  { name: "الهندسة", members: 21, budget: "٤٨٬٥٠٠" },
]

export function TableRtl() {
  return (
    <div dir="rtl" className="w-full">
      <Table variant="surface">
        <TableHeader>
          <TableRow>
            <TableHead>الفريق</TableHead>
            <TableHead align="end">الأعضاء</TableHead>
            <TableHead align="end">الميزانية</TableHead>
          </TableRow>
        </TableHeader>
        <TableBody>
          {rows.map((row) => (
            <TableRow key={row.name}>
              <TableHead scope="row">{row.name}</TableHead>
              <TableCell align="end">{row.members}</TableCell>
              <TableCell align="end">{row.budget}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </div>
  )
}
TuşAction
TabTablo taştığında kaydırma alanına, sonra içindeki bağlantılara ve düğmelere odaklanır.
←→Odaktaki, taşan bir tabloyu yana kaydırır.
↑↓Sticky başlıklı odaktaki bir tabloyu yukarı aşağı kaydırır.
  • Parçalar yerel tablo öğelerini işler, böylece ekran okuyucular fazladan rol olmadan satırları, sütunları ve başlıkları duyurur.
  • Her değer satırı ve sütunuyla birlikte okunsun diye bir satırı adlandıran hücreyi <TableHead scope="row"> ile işaretleyin.
  • Kaydırma alanı sekme sırasına yalnızca taşarken girer; böylece sığan tablolar fazladan bir durak eklemez.

Her parça kendi yerel öğesini işler ve niteliklerini kabul eder.

PropTürVarsayılan
variantsurface yuvarlak, ince çizgili bir çerçeve ve soluk bir başlık bandı ekler.
"default" | "surface""default"
size
"sm" | "default""default"
wrapHücre metninin sarmasına izin verir ve satırları üste hizalar.
booleanfalse
scrollFadeKaydırılacak daha fazla içeriği olan kenarları soldurur. Sütunlar sabitlendiğinde atlanır.
booleantrue
stickyHeaderBaşlığı görünümde tutar. containerClassName ile kapsayıcıya bir azami yükseklik verin.
booleanfalse
containerClassNameKaydırma kapsayıcısı için sınıflar.
string–
containerRefKaydırma kapsayıcısına ref.
Ref<HTMLDivElement>–
ÖznitelikAçıklama
data-slot="table-frame"Dış çerçeve; data-variant, data-size ve data-wrap ile.
data-slot="table-container"Kaydırma kapsayıcısı.
data-overflowingİçeriği taştığında kapsayıcıda bulunur. O zaman odaklanabilir.
data-scrolled-start / data-scrolled-endGörünür alanın öncesinde veya sonrasında gizli içerik olduğunda bulunur.
data-scrolled-topSticky başlıklı bir tablo kaydırıldığında bulunur.
--table-bgSatır arka planı. Çevreleyen bir kart veya popover'ı izler.
--table-head-bgSurface varyantında başlık bandı arka planı.
--table-cell-px / --table-cell-pyHücre dolgusu. size ile belirlenir.
PropTürVarsayılan
scopeBir satırı adlandıran hücre için row kullanın. Gövdenin içinde hücre dolgusu ve ön plan metni alır.
"col" | "row"–
alignend ayrıca haneler hizalansın diye tabular sayılara geçer.
"start" | "center" | "end""start"
pinnedTablo yana kayarken sütunu görünümde tutar. Aynı değeri başlığına ve her hücresine verin.
"start" | "end"–
pinnedEdgeİçerik arkasında gizliyken son sabitlenmiş sütunun iç kenarına yumuşak bir gölge çizer.
booleanfalse
ÖznitelikAçıklama
data-slot="table-head"CSS'te başlık hücrelerini hedefler.
data-alignHizalama.
data-pinnedSabitlenen taraf.
PropTürVarsayılan
alignend ayrıca haneler hizalansın diye tabular sayılara geçer.
"start" | "center" | "end""start"
pinnedTablo yana kayarken sütunu görünümde tutar. Aynı değeri başlığına ve her hücresine verin.
"start" | "end"–
pinnedEdgeİçerik arkasında gizliyken son sabitlenmiş sütunun iç kenarına yumuşak bir gölge çizer.
booleanfalse
ÖznitelikAçıklama
data-slot="table-cell"CSS'te hücreleri hedefler.
data-alignHizalama.
data-pinnedSabitlenen taraf.
ÖznitelikAçıklama
data-slot="table-row"CSS'te satırları hedefler.
data-state="selected"Seçili bir satırı vurgulamak için ayarlayın.
ÖznitelikAçıklama
data-slot="table-header"thead.
data-slot="table-body"tbody.
data-slot="table-footer"Başlık bandı renginde tfoot.
data-slot="table-caption"Tablonun altında. Surface varyantında çerçevenin içinde durur.

Kullanıldığı bloklar

Table üzerine kurulan bloklar.