---
title: Table
description: A clear layout for structured rows and columns.
group: Components
order: 65
---

Display invoices, products, and other structured data in familiar rows and columns.

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

const invoices = [
  { invoice: "INV001", status: "Paid", method: "Credit Card", amount: "$250.00" },
  { invoice: "INV002", status: "Pending", method: "PayPal", amount: "$150.00" },
  { invoice: "INV003", status: "Unpaid", method: "Bank Transfer", amount: "$350.00" },
  { invoice: "INV004", status: "Paid", method: "Credit Card", amount: "$450.00" },
  { invoice: "INV005", status: "Paid", method: "PayPal", amount: "$550.00" },
  { invoice: "INV006", status: "Pending", method: "Bank Transfer", amount: "$200.00" },
  { invoice: "INV007", status: "Unpaid", method: "Credit Card", amount: "$300.00" },
]

export function Example() {
  return (
    <div>
      <Table>
        <TableHeader>
          <TableRow>
            <TableHead className="w-[100px]">Invoice</TableHead>
            <TableHead>Status</TableHead>
            <TableHead>Method</TableHead>
            <TableHead className="text-right">Amount</TableHead>
          </TableRow>
        </TableHeader>
        <TableBody>
          {invoices.map((row) => (
            <TableRow key={row.invoice}>
              <TableCell className="font-medium">{row.invoice}</TableCell>
              <TableCell>{row.status}</TableCell>
              <TableCell>{row.method}</TableCell>
              <TableCell className="text-right">{row.amount}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
      <TableCaption>A list of your recent invoices.</TableCaption>
    </div>
  )
}
```

## Installation

```bash
npx @arctis-sh/@arctis-sh/ui@latest add table
```

## Usage

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

```tsx
<div>
  <Table>
    <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>
  <TableCaption>Recent invoices.</TableCaption>
</div>
```

## Composition

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

## Footer

Add `TableFooter` for totals or other summary content below the body.

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

const invoices = [
  { invoice: "INV001", status: "Paid", method: "Credit Card", amount: "$250.00" },
  { invoice: "INV002", status: "Pending", method: "PayPal", amount: "$150.00" },
  { invoice: "INV003", status: "Unpaid", method: "Bank Transfer", amount: "$350.00" },
]

export function Example() {
  return (
    <div>
      <Table>
        <TableHeader>
          <TableRow>
            <TableHead className="w-[100px]">Invoice</TableHead>
            <TableHead>Status</TableHead>
            <TableHead>Method</TableHead>
            <TableHead className="text-right">Amount</TableHead>
          </TableRow>
        </TableHeader>
        <TableBody>
          {invoices.map((row) => (
            <TableRow key={row.invoice}>
              <TableCell className="font-medium">{row.invoice}</TableCell>
              <TableCell>{row.status}</TableCell>
              <TableCell>{row.method}</TableCell>
              <TableCell className="text-right">{row.amount}</TableCell>
            </TableRow>
          ))}
        </TableBody>
        <TableFooter>
          <TableRow>
            <TableCell colSpan={3}>Total</TableCell>
            <TableCell className="text-right">$750.00</TableCell>
          </TableRow>
        </TableFooter>
      </Table>
      <TableCaption>A list of your recent invoices.</TableCaption>
    </div>
  )
}
```

## Actions

Place a `DropdownMenu` in a cell for actions that belong to a single row.

```tsx
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const products = [
  { name: "Wireless Mouse", price: "$29.99" },
  { name: "Mechanical Keyboard", price: "$129.99" },
  { name: "USB-C Hub", price: "$49.99" },
]

export function Example() {
  return (
    <Table>
      <TableHeader>
        <TableRow>
          <TableHead>Product</TableHead>
          <TableHead>Price</TableHead>
          <TableHead className="w-[70px] text-right">
            <span className="sr-only">Actions</span>
          </TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {products.map((product) => (
          <TableRow key={product.name}>
            <TableCell className="font-medium">{product.name}</TableCell>
            <TableCell>{product.price}</TableCell>
            <TableCell className="text-right">
              <DropdownMenu>
                <DropdownMenuTrigger
                  aria-label="Open menu"
                  className="inline-flex size-6 shrink-0 items-center justify-center rounded-sm text-foreground/50 transition-colors duration-200 ease-out hover:bg-surface-hover hover:text-foreground aria-expanded:bg-surface-hover aria-expanded:text-foreground"
                >
                  <MoreHorizontalIcon className="size-3.5" />
                </DropdownMenuTrigger>
                <DropdownMenuContent align="end">
                  <DropdownMenuItem>Edit</DropdownMenuItem>
                  <DropdownMenuItem>Duplicate</DropdownMenuItem>
                  <DropdownMenuItem>Delete</DropdownMenuItem>
                </DropdownMenuContent>
              </DropdownMenu>
            </TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  )
}
```

## Data Table

Need sorting, filtering, pagination, or row selection? See [Data Table](/docs/components/data-table).

## API Reference

### Table

| Prop | Type | Default |
| --- | --- | --- |
| className | string | — |

Also accepts the other native `table` attributes.

```tsx
<Table>
  <TableHeader>
    <TableRow>
      <TableHead>Name</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>Mina</TableCell>
    </TableRow>
  </TableBody>
</Table>
```

### TableHeader

| Prop | Type | Default |
| --- | --- | --- |
| className | string | — |

Also accepts the other native `thead` attributes.

```tsx
<TableHeader>
  <TableRow>
    <TableHead>Name</TableHead>
  </TableRow>
</TableHeader>
```

### TableBody

| Prop | Type | Default |
| --- | --- | --- |
| className | string | — |

Also accepts the other native `tbody` attributes.

```tsx
<TableBody>
  <TableRow>
    <TableCell>Mina</TableCell>
  </TableRow>
</TableBody>
```

### TableFooter

| Prop | Type | Default |
| --- | --- | --- |
| className | string | — |

Also accepts the other native `tfoot` attributes.

```tsx
<TableFooter>
  <TableRow>
    <TableCell>Total</TableCell>
  </TableRow>
</TableFooter>
```

### TableRow

| Prop | Type | Default |
| --- | --- | --- |
| className | string | — |

Also accepts the other native `tr` attributes. Set `data-state="selected"` for a selected row.

```tsx
<TableRow>
  <TableCell>Mina</TableCell>
</TableRow>
```

### TableHead

| Prop | Type | Default |
| --- | --- | --- |
| className | string | — |

Also accepts the other native `th` attributes.

```tsx
<TableHead>Name</TableHead>
```

### TableCell

| Prop | Type | Default |
| --- | --- | --- |
| className | string | — |

Also accepts the other native `td` attributes.

```tsx
<TableCell>Mina</TableCell>
```

### TableCaption

Place `TableCaption` next to `Table`, not inside it.

| Prop | Type | Default |
| --- | --- | --- |
| className | string | — |

Also accepts the other native `div` attributes.

```tsx
<TableCaption>A list of people.</TableCaption>
```

## Source

```tsx
import type { ComponentProps } from "react";
import { cn } from "@/lib/utils";

export function Table({ className, ...props }: ComponentProps<"table">) {
  return (
    <div
      data-slot="table-container"
      className="relative w-full overflow-x-auto overflow-y-hidden rounded-md bg-surface"
    >
      <table
        data-slot="table"
        className={cn("w-full text-left text-sm tracking-wide", className)}
        {...props}
      />
    </div>
  );
}

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

export function TableBody({ className, ...props }: ComponentProps<"tbody">) {
  return (
    <tbody
      data-slot="table-body"
      className={cn(
        "[&_tr]:transition-colors [&_tr]:duration-200 [&_tr]:ease-out",
        "[&_tr]:hover:bg-surface-hover",
        "[&_tr]:has-[[aria-expanded=true]]:bg-surface-hover",
        "[&_tr]:data-[state=selected]:bg-surface-hover",
        "[&_tr:last-child]:border-0",
        className,
      )}
      {...props}
    />
  );
}

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

export function TableRow({ className, ...props }: ComponentProps<"tr">) {
  return (
    <tr
      data-slot="table-row"
      className={cn("border-b border-border", className)}
      {...props}
    />
  );
}

export function TableHead({ className, ...props }: ComponentProps<"th">) {
  return (
    <th
      data-slot="table-head"
      className={cn(
        "px-3 py-2 text-left align-middle font-normal tracking-wide whitespace-nowrap text-muted-foreground",
        className,
      )}
      {...props}
    />
  );
}

export function TableCell({ className, ...props }: ComponentProps<"td">) {
  return (
    <td
      data-slot="table-cell"
      className={cn(
        "px-3 py-2 align-middle tracking-wide whitespace-nowrap",
        className,
      )}
      {...props}
    />
  );
}

export function TableCaption({ className, ...props }: ComponentProps<"div">) {
  return (
    <div
      data-slot="table-caption"
      className={cn("mt-3 text-center text-sm text-muted-foreground", className)}
      {...props}
    />
  );
}
```
