Table

A responsive table component for displaying structured data with headers, rows, and optional footer and caption.

Usage

Basic Table

import { 
  Table, 
  TableHeader, 
  TableBody, 
  TableHead, 
  TableRow, 
  TableCell 
} from "@prisma-docs/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:

NameTypeDescription
idStringUnique identifier
nameStringUser's full name
emailStringUser's email address

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:

FieldTypeDescription
idStringUnique identifier
nameStringUser's full name
emailStringUser's email address

Table with Caption

import { 
  Table, 
  TableHeader, 
  TableBody, 
  TableHead, 
  TableRow, 
  TableCell,
  TableCaption 
} from "@prisma-docs/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:

User database schema
Down the rabbit hole
FieldTypeRequired
idIntYes
emailStringYes
avatarStringNo

Table with Footer

import { 
  Table, 
  TableHeader, 
  TableBody,
  TableFooter, 
  TableHead, 
  TableRow, 
  TableCell 
} from "@prisma-docs/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:

ProductQuantityPrice
Prisma ORM1$0
Prisma Accelerate1$29
Prisma Pulse1$99
Total$128

Alignment Options

import { 
  Table, 
  TableHeader, 
  TableBody, 
  TableHead, 
  TableRow, 
  TableCell 
} from "@prisma-docs/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:

Left AlignedCenter AlignedRight Aligned
DefaultCentered100
TextContent200

Component Props

Table

  • className - Additional CSS classes (optional)
  • children - Table content (required)
  • All standard HTML table attributes are supported

TableHeader

  • className - Additional CSS classes (optional)
  • children - Header rows (required)
  • All standard HTML thead attributes are supported

TableBody

  • className - Additional CSS classes (optional)
  • children - Body rows (required)
  • All standard HTML tbody attributes are supported

TableFooter

  • className - Additional CSS classes (optional)
  • children - Footer rows (required)
  • All standard HTML tfoot attributes are supported

TableRow

  • className - Additional CSS classes (optional)
  • children - Table cells (required)
  • All standard HTML tr attributes are supported

TableHead

  • className - Additional CSS classes (optional)
  • children - Header content (required)
  • All standard HTML th attributes are supported (colSpan, rowSpan, etc.)

TableCell

  • className - Additional CSS classes (optional)
  • children - Cell content (required)
  • All standard HTML td attributes are supported (colSpan, rowSpan, etc.)

TableCaption

  • className - Additional CSS classes (optional)
  • children - Caption text (required)
  • All standard HTML caption attributes are supported

Features

  • ✅ Responsive with horizontal scrolling on overflow
  • ✅ Hover states on table rows
  • ✅ Border styling with Eclipse design tokens
  • ✅ Support for header, body, and footer sections
  • ✅ Optional caption for accessibility
  • ✅ Customizable alignment (left, center, right)
  • ✅ Support for colspan and rowspan
  • ✅ Semantic HTML structure
  • ✅ Accessible by default
  • ✅ Works with markdown table syntax

Best Practices

  • Use TableHeader for column headings to improve accessibility
  • Use TableCaption to provide context about the table's content
  • Align numbers to the right for better readability
  • Keep tables simple - avoid nesting tables
  • Use consistent column widths when possible
  • Consider mobile responsiveness - tables scroll horizontally
  • Use meaningful header text that describes the column data
  • Add hover states for better user experience (built-in)
  • Use TableFooter for summary rows or totals
  • Avoid overly complex tables - break them into multiple simple tables if needed

Common Patterns

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>

Accessibility

  • Use <TableHeader> for proper table header semantics
  • Use <TableCaption> to describe table content for screen readers
  • Tables are keyboard navigable
  • Proper HTML table structure ensures screen reader compatibility
  • Use meaningful header text that describes column content
  • Avoid using tables for layout purposes
  • Consider adding scope attribute to header cells for complex tables
  • Ensure sufficient color contrast in table content

Responsive Behavior

The Table component automatically handles overflow:

  • Tables are wrapped in a scrollable container
  • Horizontal scrolling is enabled when content exceeds viewport width
  • No content is hidden or truncated
  • Scroll behavior is smooth and native
  • Mobile-friendly touch scrolling

For better mobile experience, consider:

  • Reducing the number of columns on small screens
  • Using a card layout instead of a table for very small screens
  • Making column widths responsive
  • Prioritizing essential data in leftmost columns

Styling Guidelines

The Table component follows Eclipse design system principles:

  • Borders: Subtle borders between rows and sections
  • Hover: Smooth hover states on rows
  • Spacing: Consistent padding (p-2) in cells
  • Typography: Small font size (text-sm) for density
  • Alignment: Left-aligned by default, customizable per cell
  • Colors: Uses muted colors for backgrounds and borders

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>

Integration with Data

With Static Data

const users = [
  { id: 1, name: "Alice", email: "alice@example.com" },
  { id: 2, name: "Bob", email: "bob@example.com" },
];

<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>
  );
}

On this page