Table

A responsive table for displaying tabular data.
A list of your recent invoices.
InvoiceStatusMethodAmount
INV001PaidCredit Card$250.00
INV002PendingPayPal$150.00
INV003UnpaidBank Transfer$350.00
Total$750.00
Installation
Expand

npx @left4code/cosmic-ui-cli@latest add table
 
Expand

This writes the component and everything it imports, then installs the packages it needs. Run npx @left4code/cosmic-ui-cli@latest initfirst if you haven't already.

No state machine here - a table doesn't need one, it's semantic HTML (table > thead/tbody/tfoot) wrapped in a horizontally scrolling container so wide tables don't blow out the layout on small screens. Or copy and paste the code below by hand.

components/ui/table.tsx
Expand

import { twMerge } from "tailwind-merge";

function TableRoot({
  children,
  className,
}: React.PropsWithChildren<{ className?: string }>) {
  return (
    <div className="relative w-full overflow-x-auto">
      <table className={twMerge(["w-full border-collapse", className])}>
        {children}
      </table>
    </div>
  );
}

function TableHeader({
  children,
  className,
}: React.PropsWithChildren<{ className?: string }>) {
  return <thead className={twMerge(["border-b border-primary/30", className])}>{children}</thead>;
}

function TableBody({
  children,
  className,
}: React.PropsWithChildren<{ className?: string }>) {
  return (
    <tbody className={twMerge(["[&_tr:last-child]:border-0", className])}>{children}</tbody>
  );
}

function TableFooter({
  children,
  className,
}: React.PropsWithChildren<{ className?: string }>) {
  return (
    <tfoot className={twMerge(["border-t border-primary/30 font-medium", className])}>
      {children}
    </tfoot>
  );
}

function TableRow({
  children,
  className,
}: React.PropsWithChildren<{ className?: string }>) {
  return (
    <tr className={twMerge(["border-b border-primary/10 hover:bg-primary/5", className])}>
      {children}
    </tr>
  );
}

function TableHead({
  children,
  className,
}: React.PropsWithChildren<{ className?: string }>) {
  return (
    <th
      className={twMerge([
        "h-10 px-4 text-left align-middle font-medium text-foreground/70",
        className,
      ])}
    >
      {children}
    </th>
  );
}

function TableCell({
  children,
  className,
  colSpan,
}: React.PropsWithChildren<{ className?: string; colSpan?: number }>) {
  return (
    <td colSpan={colSpan} className={twMerge(["p-4 align-middle", className])}>
      {children}
    </td>
  );
}

function TableCaption({
  children,
  className,
}: React.PropsWithChildren<{ className?: string }>) {
  return <caption className={twMerge(["mt-4 opacity-70", className])}>{children}</caption>;
}

export {
  TableRoot,
  TableHeader,
  TableBody,
  TableFooter,
  TableRow,
  TableHead,
  TableCell,
  TableCaption,
};
 
Expand

Update the import paths to match your project setup.

Usage
Expand

import {
  TableRoot,
  TableHeader,
  TableBody,
  TableFooter,
  TableRow,
  TableHead,
  TableCell,
  TableCaption,
} from "@/components/ui/table";
 
Expand
Expand

<TableRoot>
  <TableHeader>
    <TableRow>
      <TableHead>Name</TableHead>
      <TableHead>Role</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>Ada</TableCell>
      <TableCell>Engineer</TableCell>
    </TableRow>
  </TableBody>
</TableRoot>
 
Expand
Powered by synthetic caffeine · Deployed by Left4code · Signal traceable on GitHub.