Lewati ke konten

Tabel

Tabel HTML semantik untuk faktur, daftar admin, dan tabel harga — baris bergaris tepi, judul tebal, serta bayangan bergaya neobrutalis yang tegas.

import {
  Table,
  TableBody,

Komponen table menggayakan elemen tabel HTML natif — <table>, <thead>, <tbody>, <th>, <td>, <caption> — tanpa pustaka primitif di baliknya; varian Radix dan Base memakai berkas yang sama. Resep neobrutalisnya: garis tepi tebal dan bayangan keras mengelilingi seluruh tabel, sel header memakai font judul, dan pembatas antarbaris setebal 2px.

Cocok digunakan untuk:

  • Faktur dan pesanan — butir-butir transaksi dengan baris TableFooter untuk totalnya.
  • Daftar admin — pengguna, kunci API, langganan, dengan dropdown aksi per baris.
  • Kisi harga dan perbandingan — matriks fitur yang maknanya dibawa oleh header kolom.

Instalasi

pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/table.json
npx shadcn@latest add https://neobrutalism.com/r/base/table.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/table.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/table.json

Salin dan tempel kode berikut ke dalam proyek Anda.

components/ui/table.tsx
"use client"

import * as React from "react"

import { cn } from "@/lib/utils"

function Table({ className, ...props }: React.ComponentProps<"table">) {
  return (
    <div
      data-slot="table-container"
      className="relative w-full overflow-x-auto rounded border-2 shadow-md"
    >
      <table
        data-slot="table"
        className={cn("w-full caption-bottom text-sm", className)}
        {...props}
      />
    </div>
  )
}

function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
  return (
    <thead
      data-slot="table-header"
      className={cn("[&_tr]:border-b-2", className)}
      {...props}
    />
  )
}

function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
  return (
    <tbody
      data-slot="table-body"
      className={cn("[&_tr:last-child]:border-0", className)}
      {...props}
    />
  )
}

function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
  return (
    <tfoot
      data-slot="table-footer"
      className={cn(
        "border-t-2 bg-muted/50 font-medium [&>tr]:last:border-b-0",
        className
      )}
      {...props}
    />
  )
}

function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
  return (
    <tr
      data-slot="table-row"
      className={cn(
        "border-b-2 transition-colors hover:bg-accent has-aria-expanded:bg-accent data-[state=selected]:bg-accent",
        className
      )}
      {...props}
    />
  )
}

function TableHead({ className, ...props }: React.ComponentProps<"th">) {
  return (
    <th
      data-slot="table-head"
      className={cn(
        "h-10 bg-muted px-2 text-left align-middle font-head font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
        className
      )}
      {...props}
    />
  )
}

function TableCell({ className, ...props }: React.ComponentProps<"td">) {
  return (
    <td
      data-slot="table-cell"
      className={cn(
        "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
        className
      )}
      {...props}
    />
  )
}

function TableCaption({
  className,
  ...props
}: React.ComponentProps<"caption">) {
  return (
    <caption
      data-slot="table-caption"
      className={cn("mt-4 text-sm text-muted-foreground", className)}
      {...props}
    />
  )
}

export {
  Table,
  TableHeader,
  TableBody,
  TableFooter,
  TableHead,
  TableRow,
  TableCell,
  TableCaption,
}

Sesuaikan jalur impor dengan pengaturan proyek Anda.

Penggunaan

import {
  Table,
  TableBody,
  TableCaption,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
<Table>
  <TableCaption>A list of your recent invoices.</TableCaption>
  <TableHeader>
    <TableRow>
      <TableHead className="w-[100px]">Invoice</TableHead>
      <TableHead>Status</TableHead>
      <TableHead>Method</TableHead>
      <TableHead className="text-right">Amount</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell className="font-medium">INV001</TableCell>
      <TableCell>Paid</TableCell>
      <TableCell>Credit Card</TableCell>
      <TableCell className="text-right">$250.00</TableCell>
    </TableRow>
  </TableBody>
</Table>

Komposisi

Gunakan komposisi berikut untuk membangun Table:

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

Contoh

Gunakan komponen <TableFooter /> untuk menambahkan footer ke tabel.

import {
  Table,
  TableBody,

Tindakan

Tabel yang menampilkan tindakan untuk setiap baris menggunakan komponen <DropdownMenu />.

import { MoreHorizontalIcon } from "lucide-react"

import { Button } from "@/components/ui/button"

Data Table

Anda dapat menggunakan komponen <Table /> untuk membangun tabel data yang lebih kompleks. Kombinasikan dengan @tanstack/react-table untuk membuat tabel dengan pengurutan, pemfilteran, dan penomoran halaman.

Lihat dokumentasi Data Table untuk informasi lebih lanjut.

Anda juga dapat melihat contoh tabel data di demo Tasks.

RTL

Untuk mengaktifkan dukungan RTL di Neobrutalism, lihat panduan konfigurasi RTL.

"use client"

import * as React from "react"

Aksesibilitas

Merender elemen tabel natif memberi pembaca layar pengumuman tabel, navigasi baris/kolom, dan asosiasi header tanpa perkabelan ARIA apa pun. Namai setiap tabel dengan TableCaption dan pakai TableHead hanya untuk sel header sungguhan. Kontainer gulirnya tidak dapat difokus, sehingga pengguna yang hanya memakai keyboard tidak bisa menggulir tabel yang meluap — jika tabel lebar mungkin muncul, tambahkan tabIndex={0}, role="region", dan aria-label pada div kontainer di salinan komponen Anda.