apps/eclipse/content/design-system/components/table.mdx
import { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption } from "@prisma/eclipse";
Basic Table
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell
} from "@prisma/eclipse";
export function BasicTable() {
return (
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Type</TableHead>
<TableHead>Description</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>id</TableCell>
<TableCell>String</TableCell>
<TableCell>Unique identifier</TableCell>
</TableRow>
<TableRow>
<TableCell>name</TableCell>
<TableCell>String</TableCell>
<TableCell>User's full name</TableCell>
</TableRow>
<TableRow>
<TableCell>email</TableCell>
<TableCell>String</TableCell>
<TableCell>User's email address</TableCell>
</TableRow>
</TableBody>
</Table>
);
}
Live Example:
<Table> <TableHeader> <TableRow> <TableHead>Name</TableHead> <TableHead>Type</TableHead> <TableHead>Description</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow> <TableCell>id</TableCell> <TableCell>String</TableCell> <TableCell>Unique identifier</TableCell> </TableRow> <TableRow> <TableCell>name</TableCell> <TableCell>String</TableCell> <TableCell>User's full name</TableCell> </TableRow> <TableRow> <TableCell>email</TableCell> <TableCell>String</TableCell> <TableCell>User's email address</TableCell> </TableRow> </TableBody> </Table>Markdown Table Syntax
Tables written in markdown are automatically converted to use the Table component:
| Name | Type | Description |
|-------|--------|----------------------|
| id | String | Unique identifier |
| name | String | User's full name |
| email | String | User's email address |
Live Example:
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier |
| name | String | User's full name |
| String | User's email address |
Table with Caption
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell,
TableCaption
} from "@prisma/eclipse";
export function TableWithCaption() {
return (
<Table>
<TableCaption>User database schema</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Down the rabbit hole</TableHead>
</TableRow>
</TableHeader>
<TableHeader>
<TableRow>
<TableHead>Field</TableHead>
<TableHead>Type</TableHead>
<TableHead>Required</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>id</TableCell>
<TableCell>Int</TableCell>
<TableCell>Yes</TableCell>
</TableRow>
<TableRow>
<TableCell>email</TableCell>
<TableCell>String</TableCell>
<TableCell>Yes</TableCell>
</TableRow>
<TableRow>
<TableCell>avatar</TableCell>
<TableCell>String</TableCell>
<TableCell>No</TableCell>
</TableRow>
</TableBody>
</Table>
);
}
Live Example:
<Table> <TableCaption>User database schema</TableCaption> <TableHeader> <TableRow> <TableHead colSpan="3">Down the rabbit hole</TableHead> </TableRow> </TableHeader> <TableHeader> <TableRow> <TableHead>Field</TableHead> <TableHead>Type</TableHead> <TableHead>Required</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow> <TableCell>id</TableCell> <TableCell>Int</TableCell> <TableCell>Yes</TableCell> </TableRow> <TableRow> <TableCell>email</TableCell> <TableCell>String</TableCell> <TableCell>Yes</TableCell> </TableRow> <TableRow> <TableCell>avatar</TableCell> <TableCell>String</TableCell> <TableCell>No</TableCell> </TableRow> </TableBody> </Table>Table with Footer
import {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell
} from "@prisma/eclipse";
export function TableWithFooter() {
return (
<Table>
<TableHeader>
<TableRow>
<TableHead>Product</TableHead>
<TableHead>Quantity</TableHead>
<TableHead className="text-right">Price</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>Prisma ORM</TableCell>
<TableCell>1</TableCell>
<TableCell className="text-right">$0</TableCell>
</TableRow>
<TableRow>
<TableCell>Prisma Accelerate</TableCell>
<TableCell>1</TableCell>
<TableCell className="text-right">$29</TableCell>
</TableRow>
<TableRow>
<TableCell>Prisma Pulse</TableCell>
<TableCell>1</TableCell>
<TableCell className="text-right">$99</TableCell>
</TableRow>
</TableBody>
<TableFooter>
<TableRow>
<TableCell colSpan={2}>Total</TableCell>
<TableCell className="text-right">$128</TableCell>
</TableRow>
</TableFooter>
</Table>
);
}
Live Example:
<Table> <TableHeader> <TableRow> <TableHead>Product</TableHead> <TableHead>Quantity</TableHead> <TableHead className="text-right">Price</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow> <TableCell>Prisma ORM</TableCell> <TableCell>1</TableCell> <TableCell className="text-right">$0</TableCell> </TableRow> <TableRow> <TableCell>Prisma Accelerate</TableCell> <TableCell>1</TableCell> <TableCell className="text-right">$29</TableCell> </TableRow> <TableRow> <TableCell>Prisma Pulse</TableCell> <TableCell>1</TableCell> <TableCell className="text-right">$99</TableCell> </TableRow> </TableBody> <TableFooter> <TableRow> <TableCell colSpan={2}>Total</TableCell> <TableCell className="text-right">$128</TableCell> </TableRow> </TableFooter> </Table>Alignment Options
import {
Table,
TableHeader,
TableBody,
TableHead,
TableRow,
TableCell
} from "@prisma/eclipse";
export function AlignedTable() {
return (
<Table>
<TableHeader>
<TableRow>
<TableHead className="text-left">Left Aligned</TableHead>
<TableHead className="text-center">Center Aligned</TableHead>
<TableHead className="text-right">Right Aligned</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="text-left">Default</TableCell>
<TableCell className="text-center">Centered</TableCell>
<TableCell className="text-right">100</TableCell>
</TableRow>
<TableRow>
<TableCell className="text-left">Text</TableCell>
<TableCell className="text-center">Content</TableCell>
<TableCell className="text-right">200</TableCell>
</TableRow>
</TableBody>
</Table>
);
}
Live Example:
<Table> <TableHeader> <TableRow> <TableHead className="text-left">Left Aligned</TableHead> <TableHead className="text-center">Center Aligned</TableHead> <TableHead className="text-right">Right Aligned</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow> <TableCell className="text-left">Default</TableCell> <TableCell className="text-center">Centered</TableCell> <TableCell className="text-right">100</TableCell> </TableRow> <TableRow> <TableCell className="text-left">Text</TableCell> <TableCell className="text-center">Content</TableCell> <TableCell className="text-right">200</TableCell> </TableRow> </TableBody> </Table>className - Additional CSS classes (optional)children - Table content (required)className - Additional CSS classes (optional)children - Header rows (required)className - Additional CSS classes (optional)children - Body rows (required)className - Additional CSS classes (optional)children - Footer rows (required)className - Additional CSS classes (optional)children - Table cells (required)className - Additional CSS classes (optional)children - Header content (required)className - Additional CSS classes (optional)children - Cell content (required)className - Additional CSS classes (optional)children - Caption text (required)API Reference Table
<Table>
<TableCaption>Prisma Client API methods</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Method</TableHead>
<TableHead>Description</TableHead>
<TableHead>Returns</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell><code>findMany()</code></TableCell>
<TableCell>Fetch multiple records</TableCell>
<TableCell>Array</TableCell>
</TableRow>
<TableRow>
<TableCell><code>findUnique()</code></TableCell>
<TableCell>Fetch a single record</TableCell>
<TableCell>Object or null</TableCell>
</TableRow>
<TableRow>
<TableCell><code>create()</code></TableCell>
<TableCell>Create a new record</TableCell>
<TableCell>Object</TableCell>
</TableRow>
</TableBody>
</Table>
Pricing Table
<Table>
<TableHeader>
<TableRow>
<TableHead>Plan</TableHead>
<TableHead>Features</TableHead>
<TableHead className="text-right">Price</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="font-semibold">Free</TableCell>
<TableCell>Basic features</TableCell>
<TableCell className="text-right">$0/mo</TableCell>
</TableRow>
<TableRow>
<TableCell className="font-semibold">Pro</TableCell>
<TableCell>Advanced features</TableCell>
<TableCell className="text-right">$29/mo</TableCell>
</TableRow>
<TableRow>
<TableCell className="font-semibold">Enterprise</TableCell>
<TableCell>All features + support</TableCell>
<TableCell className="text-right">Custom</TableCell>
</TableRow>
</TableBody>
</Table>
Comparison Table
<Table>
<TableHeader>
<TableRow>
<TableHead>Feature</TableHead>
<TableHead className="text-center">Prisma ORM</TableHead>
<TableHead className="text-center">Other ORMs</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>Type Safety</TableCell>
<TableCell className="text-center">✅</TableCell>
<TableCell className="text-center">❌</TableCell>
</TableRow>
<TableRow>
<TableCell>Auto-completion</TableCell>
<TableCell className="text-center">✅</TableCell>
<TableCell className="text-center">⚠️</TableCell>
</TableRow>
<TableRow>
<TableCell>Migrations</TableCell>
<TableCell className="text-center">✅</TableCell>
<TableCell className="text-center">✅</TableCell>
</TableRow>
</TableBody>
</Table>
Status Table
<Table>
<TableHeader>
<TableRow>
<TableHead>Service</TableHead>
<TableHead>Status</TableHead>
<TableHead>Uptime</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>Prisma Data Platform</TableCell>
<TableCell>
<span className="inline-flex items-center gap-1 text-foreground-success">
<span className="size-2 rounded-full bg-foreground-success" />
Operational
</span>
</TableCell>
<TableCell>99.9%</TableCell>
</TableRow>
<TableRow>
<TableCell>Prisma Accelerate</TableCell>
<TableCell>
<span className="inline-flex items-center gap-1 text-foreground-success">
<span className="size-2 rounded-full bg-foreground-success" />
Operational
</span>
</TableCell>
<TableCell>99.99%</TableCell>
</TableRow>
</TableBody>
</Table>
<TableHeader> for proper table header semantics<TableCaption> to describe table content for screen readersscope attribute to header cells for complex tablesThe Table component automatically handles overflow:
For better mobile experience, consider:
The Table component follows Eclipse design system principles:
Override styles as needed:
<Table className="text-base">
<TableHeader className="bg-background-neutral">
<TableRow className="hover:bg-background-neutral-strong">
<TableHead className="font-bold p-4">Custom Styling</TableHead>
</TableRow>
</TableHeader>
</Table>
With Static Data
const users = [
{ id: 1, name: "Alice", email: "[email protected]" },
{ id: 2, name: "Bob", email: "[email protected]" },
];
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Email</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{users.map((user) => (
<TableRow key={user.id}>
<TableCell>{user.name}</TableCell>
<TableCell>{user.email}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
With Dynamic Data
import { useQuery } from "@tanstack/react-query";
export function UserTable() {
const { data, isLoading } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
});
if (isLoading) return <div>Loading...</div>;
return (
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Email</TableHead>
<TableHead>Role</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{data?.map((user) => (
<TableRow key={user.id}>
<TableCell>{user.name}</TableCell>
<TableCell>{user.email}</TableCell>
<TableCell>{user.role}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
}