Skip to content
Esc
navigateopen⌘Jpreview
On this page

Table

A responsive table component.

A list of your recent invoices.
InvoiceStatusMethodAmount
INV001PaidCredit card$250.00
INV002PendingPayPal$150.00
INV003UnpaidBank transfer$350.00
INV004PaidCredit card$450.00
Total$1,200.00
import * as stylex from '@stylexjs/stylex';

import {
  Table,
  TableBody,
  TableCaption,
  TableCell,
  TableFooter,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table';
import { container } from '@/lib/constants.stylex';

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' },
];

export default function TableDemo() {
  return (
    <div {...stylex.props(styles.root)}>
      <Table>
        <TableCaption>A list of your recent invoices.</TableCaption>
        <TableHeader>
          <TableRow>
            <TableHead>Invoice</TableHead>
            <TableHead>Status</TableHead>
            <TableHead>Method</TableHead>
            <TableHead style={styles.right}>Amount</TableHead>
          </TableRow>
        </TableHeader>
        <TableBody>
          {invoices.map((row) => (
            <TableRow key={row.invoice}>
              <TableCell>{row.invoice}</TableCell>
              <TableCell>{row.status}</TableCell>
              <TableCell>{row.method}</TableCell>
              <TableCell style={styles.right}>{row.amount}</TableCell>
            </TableRow>
          ))}
        </TableBody>
        <TableFooter>
          <TableRow>
            <TableCell colSpan={3}>Total</TableCell>
            <TableCell style={styles.right}>$1,200.00</TableCell>
          </TableRow>
        </TableFooter>
      </Table>
    </div>
  );
}

const styles = stylex.create({
  root: {
    maxWidth: container.xl,
    width: '100%',
  },
  right: {
    textAlign: 'right',
  },
});

Install

npx shadcn@latest add @madeui/table

Usage

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

Composition

<Table>
  <TableCaption />
  <TableHeader>
    <TableRow>
      <TableHead />
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell />
    </TableRow>
  </TableBody>
  <TableFooter />
</Table>
InvoiceMethodAmount
INV001Credit card$250.00
INV002PayPal$150.00
INV003Bank transfer$350.00
Total$750.00
import * as stylex from '@stylexjs/stylex';

import {
  Table,
  TableBody,
  TableCell,
  TableFooter,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table';
import { container } from '@/lib/constants.stylex';

const invoices = [
  { invoice: 'INV001', method: 'Credit card', amount: 250 },
  { invoice: 'INV002', method: 'PayPal', amount: 150 },
  { invoice: 'INV003', method: 'Bank transfer', amount: 350 },
];

const total = invoices.reduce((sum, row) => sum + row.amount, 0);

export default function TableFooterExample() {
  return (
    <div {...stylex.props(styles.root)}>
      <Table>
        <TableHeader>
          <TableRow>
            <TableHead>Invoice</TableHead>
            <TableHead>Method</TableHead>
            <TableHead style={styles.right}>Amount</TableHead>
          </TableRow>
        </TableHeader>
        <TableBody>
          {invoices.map((row) => (
            <TableRow key={row.invoice}>
              <TableCell>{row.invoice}</TableCell>
              <TableCell>{row.method}</TableCell>
              <TableCell style={styles.right}>${row.amount.toFixed(2)}</TableCell>
            </TableRow>
          ))}
        </TableBody>
        <TableFooter>
          <TableRow>
            <TableCell colSpan={2}>Total</TableCell>
            <TableCell style={styles.right}>${total.toFixed(2)}</TableCell>
          </TableRow>
        </TableFooter>
      </Table>
    </div>
  );
}

const styles = stylex.create({
  root: {
    maxWidth: container.lg,
    width: '100%',
  },
  right: {
    textAlign: 'right',
  },
});

Actions

A table showing per-row actions using a DropdownMenu.

NameRole
Ada LovelaceOwner
Grace HopperAdmin
Margaret HamiltonMember
import * as stylex from '@stylexjs/stylex';

import { Button } from '@/components/ui/button';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table';
import { container } from '@/lib/constants.stylex';

const members = [
  { name: 'Ada Lovelace', role: 'Owner' },
  { name: 'Grace Hopper', role: 'Admin' },
  { name: 'Margaret Hamilton', role: 'Member' },
];

function DotsIcon() {
  return (
    <svg width="16" height="16" viewBox={`0 0 16 16`} fill="currentColor" aria-hidden>
      <circle cx="8" cy="3" r="1.25" />
      <circle cx="8" cy="8" r="1.25" />
      <circle cx="8" cy="13" r="1.25" />
    </svg>
  );
}

export default function TableActions() {
  return (
    <div {...stylex.props(styles.root)}>
      <Table>
        <TableHeader>
          <TableRow>
            <TableHead>Name</TableHead>
            <TableHead>Role</TableHead>
            <TableHead style={styles.right} />
          </TableRow>
        </TableHeader>
        <TableBody>
          {members.map((member) => (
            <TableRow key={member.name}>
              <TableCell>{member.name}</TableCell>
              <TableCell>{member.role}</TableCell>
              <TableCell style={styles.right}>
                <DropdownMenu>
                  <DropdownMenuTrigger
                    render={<Button variant="ghost" size="icon" aria-label="Row actions" />}
                  >
                    <DotsIcon />
                  </DropdownMenuTrigger>
                  <DropdownMenuContent align="end">
                    <DropdownMenuItem>Edit role</DropdownMenuItem>
                    <DropdownMenuItem>Copy email</DropdownMenuItem>
                    <DropdownMenuSeparator />
                    <DropdownMenuItem variant="destructive">Remove</DropdownMenuItem>
                  </DropdownMenuContent>
                </DropdownMenu>
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </div>
  );
}

const styles = stylex.create({
  root: {
    maxWidth: container.lg,
    width: '100%',
  },
  right: {
    textAlign: 'right',
  },
});

API reference

Plain semantic table markup — Table wraps the <table> in an overflow-x: auto container for horizontal scrolling on small screens. Every part accepts its native element props plus a style prop (StyleXStyles, merged last).

Was this page helpful?