Bảng
Một bảng HTML mang tính ngữ nghĩa dành cho hóa đơn, danh sách quản trị và bảng giá — các hàng có viền, tiêu đề in đậm và hiệu ứng bóng theo phong cách tân thô mộc.
import {
Table,
TableBody,Table tạo kiểu cho các phần tử bảng HTML native — <table>, <thead>, <tbody>, <th>, <td>, <caption> — không có thư viện primitive nào bên dưới; biến thể Radix và Base dùng chung một tệp. Công thức neobrutalist ở đây: viền dày và bóng đổ đậm bao quanh cả bảng, ô tiêu đề dùng phông chữ tiêu đề, và vạch chia hàng 2px.
Nên dùng khi:
- Hóa đơn và đơn hàng — các dòng mặt hàng với một hàng
TableFootercho tổng cộng. - Danh sách quản trị — người dùng, khóa API, gói thuê bao, kèm dropdown chứa các hành động theo hàng.
- Bảng giá và bảng so sánh — ma trận tính năng nơi tiêu đề cột mang ý nghĩa chính.
Cài đặt#
pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/table.jsonnpx shadcn@latest add https://neobrutalism.com/r/base/table.jsonyarn dlx shadcn@latest add https://neobrutalism.com/r/base/table.jsonbunx --bun shadcn@latest add https://neobrutalism.com/r/base/table.json
Sao chép và dán đoạn mã sau vào dự án của bạn.
"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,
}
Cập nhật các đường dẫn import cho phù hợp với cấu hình dự án của bạn.
Cách dùng#
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>Kết hợp#
Dùng cách kết hợp sau để xây dựng một Table:
Table
├── TableCaption
├── TableHeader
│ └── TableRow
│ ├── TableHead
│ ├── TableHead
│ ├── TableHead
│ └── TableHead
├── TableBody
│ ├── TableRow
│ │ ├── TableCell
│ │ ├── TableCell
│ │ ├── TableCell
│ │ └── TableCell
│ └── TableRow
│ ├── TableCell
│ ├── TableCell
│ ├── TableCell
│ └── TableCell
└── TableFooterVí dụ#
Chân bảng#
Dùng component <TableFooter /> để thêm một chân bảng vào bảng.
import {
Table,
TableBody,Hành động#
Một bảng hiển thị các hành động cho từng hàng bằng cách dùng component <DropdownMenu />.
import { MoreHorizontalIcon } from "lucide-react"
import { Button } from "@/components/ui/button"Data Table#
Bạn có thể dùng component <Table /> để xây dựng các bảng dữ liệu phức tạp hơn. Kết hợp nó với @tanstack/react-table để tạo các bảng có sắp xếp, lọc và phân trang.
Xem tài liệu Data Table để biết thêm thông tin.
Bạn cũng có thể xem một ví dụ về bảng dữ liệu trong demo Tasks.
RTL#
Để bật hỗ trợ RTL trong Neobrutalism, xem hướng dẫn cấu hình RTL.
"use client"
import * as React from "react"Khả năng truy cập#
Việc render các phần tử bảng native mang lại cho trình đọc màn hình khả năng nhận biết bảng, điều hướng theo hàng/cột và liên kết ô với ô tiêu đề tương ứng mà không cần nối thêm ARIA. Hãy đặt tên cho mỗi bảng bằng TableCaption và chỉ dùng TableHead cho các ô tiêu đề thực sự. Vùng cuộn không focus được, nên người chỉ dùng bàn phím không thể cuộn một bảng bị tràn — nếu nhiều khả năng có bảng rộng, hãy thêm tabIndex={0}, role="region" và một aria-label vào thẻ div chứa trong bản sao thành phần của bạn.