Tablestandard
행과 열로 데이터를 보여 주는 표(table)입니다. shadcn base-nova 의 stock 아이템으로, 시맨틱 HTML 표 요소에 스타일만 입힌 얇은 부품입니다. 정렬·필터·페이지 같은 표 기능은 없으며 `@tanstack/react-table` 과 함께 쓸 수 있습니다.
설치
pnpm
pnpm dlx shadcn@4.23.0 add @uikit/tableDefault
table-example.tsx
"use client"
import { Example, ExampleWrapper,} from "@/components/example"import { Button } from "@/components/ui/button"import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger,} from "@/components/ui/dropdown-menu"import { Input } from "@/components/ui/input"import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue,} from "@/components/ui/select"import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow,} from "@/components/ui/table"import { MoreHorizontalIcon } from "lucide-react"
const invoices = [ { invoice: "INV001", paymentStatus: "Paid", totalAmount: "$250.00", paymentMethod: "Credit Card", }, { invoice: "INV002", paymentStatus: "Pending", totalAmount: "$150.00", paymentMethod: "PayPal", }, { invoice: "INV003", paymentStatus: "Unpaid", totalAmount: "$350.00", paymentMethod: "Bank Transfer", }, { invoice: "INV004", paymentStatus: "Paid", totalAmount: "$450.00", paymentMethod: "Credit Card", }, { invoice: "INV005", paymentStatus: "Paid", totalAmount: "$550.00", paymentMethod: "PayPal", }, { invoice: "INV006", paymentStatus: "Pending", totalAmount: "$200.00", paymentMethod: "Bank Transfer", }, { invoice: "INV007", paymentStatus: "Unpaid", totalAmount: "$300.00", paymentMethod: "Credit Card", },]
export default function TableExample() { return ( <ExampleWrapper> <TableBasic /> <TableWithFooter /> <TableSimple /> <TableWithBadges /> <TableWithActions /> <TableWithSelect /> <TableWithInput /> </ExampleWrapper> )}
function TableBasic() { return ( <Example title="Basic"> <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> {invoices.slice(0, 3).map((invoice) => ( <TableRow key={invoice.invoice}> <TableCell className="font-medium">{invoice.invoice}</TableCell> <TableCell>{invoice.paymentStatus}</TableCell> <TableCell>{invoice.paymentMethod}</TableCell> <TableCell className="text-right"> {invoice.totalAmount} </TableCell> </TableRow> ))} </TableBody> </Table> </Example> )}
function TableWithFooter() { return ( <Example title="With Footer"> <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> {invoices.slice(0, 3).map((invoice) => ( <TableRow key={invoice.invoice}> <TableCell className="font-medium">{invoice.invoice}</TableCell> <TableCell>{invoice.paymentStatus}</TableCell> <TableCell>{invoice.paymentMethod}</TableCell> <TableCell className="text-right"> {invoice.totalAmount} </TableCell> </TableRow> ))} </TableBody> <TableFooter> <TableRow> <TableCell colSpan={3}>Total</TableCell> <TableCell className="text-right">$2,500.00</TableCell> </TableRow> </TableFooter> </Table> </Example> )}
function TableSimple() { return ( <Example title="Simple"> <Table> <TableHeader> <TableRow> <TableHead>Name</TableHead> <TableHead>Email</TableHead> <TableHead className="text-right">Role</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow> <TableCell className="font-medium">Sarah Chen</TableCell> <TableCell className="break-all whitespace-normal">sarah.chen@acme.com</TableCell> <TableCell className="text-right">Admin</TableCell> </TableRow> <TableRow> <TableCell className="font-medium">Marc Rodriguez</TableCell> <TableCell className="break-all whitespace-normal">marcus.rodriguez@acme.com</TableCell> <TableCell className="text-right">User</TableCell> </TableRow> <TableRow> <TableCell className="font-medium">Emily Watson</TableCell> <TableCell className="break-all whitespace-normal">emily.watson@acme.com</TableCell> <TableCell className="text-right">User</TableCell> </TableRow> </TableBody> </Table> </Example> )}
function TableWithBadges() { return ( <Example title="With Badges"> <Table> <TableHeader> <TableRow> <TableHead>Task</TableHead> <TableHead>Status</TableHead> <TableHead className="text-right">Priority</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow> <TableCell className="font-medium">Design homepage</TableCell> <TableCell> <span className="inline-flex items-center rounded-full bg-green-500/10 px-2 py-1 text-xs font-medium text-green-700 dark:text-green-400"> Completed </span> </TableCell> <TableCell className="text-right"> <span className="inline-flex items-center rounded-full bg-blue-500/10 px-2 py-1 text-xs font-medium text-blue-700 dark:text-blue-400"> High </span> </TableCell> </TableRow> <TableRow> <TableCell className="font-medium">Implement API</TableCell> <TableCell> <span className="inline-flex items-center rounded-full bg-yellow-500/10 px-2 py-1 text-xs font-medium text-yellow-700 dark:text-yellow-400"> In Progress </span> </TableCell> <TableCell className="text-right"> <span className="inline-flex items-center rounded-full bg-gray-500/10 px-2 py-1 text-xs font-medium text-gray-700 dark:text-gray-400"> Medium </span> </TableCell> </TableRow> <TableRow> <TableCell className="font-medium">Write tests</TableCell> <TableCell> <span className="inline-flex items-center rounded-full bg-gray-500/10 px-2 py-1 text-xs font-medium text-gray-700 dark:text-gray-400"> Pending </span> </TableCell> <TableCell className="text-right"> <span className="inline-flex items-center rounded-full bg-gray-500/10 px-2 py-1 text-xs font-medium text-gray-700 dark:text-gray-400"> Low </span> </TableCell> </TableRow> </TableBody> </Table> </Example> )}
function TableWithActions() { return ( <Example title="With Actions"> <Table> <TableHeader> <TableRow> <TableHead>Product</TableHead> <TableHead>Price</TableHead> <TableHead className="text-right">Actions</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow> <TableCell className="font-medium">Wireless Mouse</TableCell> <TableCell>$29.99</TableCell> <TableCell className="text-right"> <DropdownMenu> <DropdownMenuTrigger render={ <Button variant="ghost" size="icon" className="size-8" /> } > <MoreHorizontalIcon /> <span className="sr-only">Open menu</span> </DropdownMenuTrigger> <DropdownMenuContent align="end"> <DropdownMenuItem>Edit</DropdownMenuItem> <DropdownMenuItem>Duplicate</DropdownMenuItem> <DropdownMenuSeparator /> <DropdownMenuItem variant="destructive"> Delete </DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> </TableCell> </TableRow> <TableRow> <TableCell className="font-medium">Mechanical Keyboard</TableCell> <TableCell>$129.99</TableCell> <TableCell className="text-right"> <DropdownMenu> <DropdownMenuTrigger render={ <Button variant="ghost" size="icon" className="size-8" /> } > <MoreHorizontalIcon /> <span className="sr-only">Open menu</span> </DropdownMenuTrigger> <DropdownMenuContent align="end"> <DropdownMenuItem>Edit</DropdownMenuItem> <DropdownMenuItem>Duplicate</DropdownMenuItem> <DropdownMenuSeparator /> <DropdownMenuItem variant="destructive"> Delete </DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> </TableCell> </TableRow> <TableRow> <TableCell className="font-medium">USB-C Hub</TableCell> <TableCell>$49.99</TableCell> <TableCell className="text-right"> <DropdownMenu> <DropdownMenuTrigger render={ <Button variant="ghost" size="icon" className="size-8" /> } > <MoreHorizontalIcon /> <span className="sr-only">Open menu</span> </DropdownMenuTrigger> <DropdownMenuContent align="end"> <DropdownMenuItem>Edit</DropdownMenuItem> <DropdownMenuItem>Duplicate</DropdownMenuItem> <DropdownMenuSeparator /> <DropdownMenuItem variant="destructive"> Delete </DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> </TableCell> </TableRow> </TableBody> </Table> </Example> )}
const people = [ { value: "sarah", label: "Sarah Chen" }, { value: "marcus", label: "Marc Rodriguez" }, { value: "emily", label: "Emily Watson" }, { value: "david", label: "David Kim" },]
const tasks = [ { task: "Design homepage", assignee: "sarah", status: "In Progress", }, { task: "Implement API", assignee: "marcus", status: "Pending", }, { task: "Write tests", assignee: "emily", status: "Not Started", },]
function TableWithSelect() { return ( <Example title="With Select"> <Table> <TableHeader> <TableRow> <TableHead>Task</TableHead> <TableHead>Assignee</TableHead> <TableHead>Status</TableHead> </TableRow> </TableHeader> <TableBody> {tasks.map((item) => ( <TableRow key={item.task}> <TableCell className="font-medium">{item.task}</TableCell> <TableCell> <Select items={people} defaultValue={people.find( (person) => person.value === item.assignee )} itemToStringValue={(item) => { return item.value }} > <SelectTrigger aria-label="Status" className="w-40" size="sm"> <SelectValue /> </SelectTrigger> <SelectContent> <SelectGroup> {people.map((person) => ( <SelectItem key={person.value} value={person}> {person.label} </SelectItem> ))} </SelectGroup> </SelectContent> </Select> </TableCell> <TableCell>{item.status}</TableCell> </TableRow> ))} </TableBody> </Table> </Example> )}
function TableWithInput() { return ( <Example title="With Input"> <Table> <TableHeader> <TableRow> <TableHead>Product</TableHead> <TableHead>Quantity</TableHead> <TableHead>Price</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow> <TableCell className="font-medium">Wireless Mouse</TableCell> <TableCell> <Input aria-label="Quantity" type="number" defaultValue="1" className="h-8 w-20" min="0" /> </TableCell> <TableCell>$29.99</TableCell> </TableRow> <TableRow> <TableCell className="font-medium">Mechanical Keyboard</TableCell> <TableCell> <Input aria-label="Quantity" type="number" defaultValue="2" className="h-8 w-20" min="0" /> </TableCell> <TableCell>$129.99</TableCell> </TableRow> <TableRow> <TableCell className="font-medium">USB-C Hub</TableCell> <TableCell> <Input aria-label="Quantity" type="number" defaultValue="1" className="h-8 w-20" min="0" /> </TableCell> <TableCell>$49.99</TableCell> </TableRow> </TableBody> </Table> </Example> )}