About
A styled, responsive table primitive with default and card variants. Ships Table, TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell and TableCaption — semantic <table> elements with hover and selected row states, a horizontal-scroll container, and a rounded 'card' layout. Dependency-free (just cn). Compose it for project lists, invoices, inventory, API metrics, server usage, subscriptions or pricing comparisons.
Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Table to your project and fits it to your theme.
Code
How Table is used: the demo's code. The component's own source comes with a free account.
Usage.tsx
import {
Table,
TableBody,
TableCell,
TableFooter,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/cnippet-table";
import type React from "react";
const badgeStyles: Record<string, string> = {
outline: "text-foreground",
secondary: "border-transparent bg-secondary text-secondary-foreground",
default: "border-transparent bg-primary text-primary-foreground",
success:
"border-transparent bg-emerald-500/15 text-emerald-600 dark:text-emerald-400",
warning:
"border-transparent bg-amber-500/15 text-amber-600 dark:text-amber-400",
destructive: "border-transparent bg-destructive/15 text-destructive",
info: "border-transparent bg-blue-500/15 text-blue-600 dark:text-blue-400",
};
function Badge({
variant = "outline",
className = "",
children,
}: {
variant?: string;
className?: string;
children?: React.ReactNode;
}): React.ReactElement {
return (
<span
className={`inline-flex items-center gap-1.5 whitespace-nowrap rounded-md border px-2 py-0.5 font-medium text-xs [&_svg]:size-3 ${badgeStyles[variant] ?? ""} ${className}`}
>
{children}
</span>
);
}
const invoices = [
{
amount: "$4,800.00",
client: "Acme Corp",
due: "Feb 5, 2025",
id: "INV-2025-001",
issued: "Jan 5, 2025",
status: "Paid",
statusVariant: "success" as const,
},
{
amount: "$2,150.00",
client: "Globex Inc",
due: "Feb 12, 2025",
id: "INV-2025-002",
issued: "Jan 12, 2025",
status: "Overdue",
statusVariant: "destructive" as const,
},
{
amount: "$9,320.00",
client: "Initech Ltd",
due: "Feb 20, 2025",
id: "INV-2025-003",
issued: "Jan 20, 2025",
status: "Pending",
statusVariant: "warning" as const,
},
{
amount: "$1,500.00",
client: "Umbrella Co",
due: "Feb 27, 2025",
id: "INV-2025-004",
issued: "Jan 27, 2025",
status: "Paid",
statusVariant: "success" as const,
},
{
amount: "$7,200.00",
client: "Cyberdyne Systems",
due: "Mar 3, 2025",
id: "INV-2025-005",
issued: "Feb 3, 2025",
status: "Draft",
statusVariant: "outline" as const,
},
];
export default function TableInvoices() {
return (
<div className="mx-auto w-full max-w-3xl">
<Table>
<TableHeader>
<TableRow>
<TableHead>Invoice</TableHead>
<TableHead>Client</TableHead>
<TableHead>Issued</TableHead>
<TableHead>Due</TableHead>
<TableHead>Status</TableHead>
<TableHead className="text-right">Amount</TableHead>
<TableHead />
</TableRow>
</TableHeader>
<TableBody>
{invoices.map((inv) => (
<TableRow key={inv.id}>
<TableCell className="font-medium font-mono text-sm">
{inv.id}
</TableCell>
<TableCell className="text-sm">{inv.client}</TableCell>
<TableCell className="text-muted-foreground text-sm">
{inv.issued}
</TableCell>
<TableCell className="text-muted-foreground text-sm">
{inv.due}
</TableCell>
<TableCell>
<Badge size="sm" variant={inv.statusVariant}>
{inv.status}
</Badge>
</TableCell>
<TableCell className="text-right font-medium text-sm">
{inv.amount}
</TableCell>
<TableCell className="text-right">
<button className="inline-flex h-7 items-center justify-center gap-1.5 whitespace-nowrap rounded-md px-2 font-medium text-foreground text-sm transition-colors hover:bg-accent hover:text-accent-foreground [&_svg]:size-3.5" type="button">
View
</button>
</TableCell>
</TableRow>
))}
</TableBody>
<TableFooter>
<TableRow>
<TableCell colSpan={5}>Total outstanding</TableCell>
<TableCell className="text-right">$11,470.00</TableCell>
<TableCell />
</TableRow>
</TableFooter>
</Table>
</div>
);
}








