SubjectFromDate
Kumo v1.0.0 releasedVisal In5 seconds ago
New Job OfferCloudflare10 minutes ago
Daily Email DigestCloudflare1 hour ago
<Table>
  <Table.Header>
    <Table.Row>
      <Table.Head>Subject</Table.Head>
      <Table.Head>From</Table.Head>
      <Table.Head>Date</Table.Head>
    </Table.Row>
  </Table.Header>
  <Table.Body>
    <Table.Row>
      <Table.Cell>Kumo v1.0.0 released</Table.Cell>
      <Table.Cell>Visal In</Table.Cell>
      <Table.Cell>5 seconds ago</Table.Cell>
    </Table.Row>
  </Table.Body>
</Table>

Installation

Barrel

import { Table } from "@cloudflare/kumo";

Granular

import { Table } from "@cloudflare/kumo/components/table";

Usage

import { Table, LayerCard } from "@cloudflare/kumo";

export default function Example() {
  return (
    <LayerCard>
      <LayerCard.Primary className="p-0">
        <Table>
          <Table.Header>
            <Table.Row>
              <Table.Head>Name</Table.Head>
              <Table.Head>Email</Table.Head>
              <Table.Head>Role</Table.Head>
            </Table.Row>
          </Table.Header>
          <Table.Body>
            <Table.Row>
              <Table.Cell>John Doe</Table.Cell>
              <Table.Cell>john@example.com</Table.Cell>
              <Table.Cell>Admin</Table.Cell>
            </Table.Row>
          </Table.Body>
        </Table>
      </LayerCard.Primary>
    </LayerCard>
  );
}

Examples

With Checkboxes

Add row selection with Table.CheckHead and Table.CheckCell.

SubjectFromDate
Kumo v1.0.0 releasedVisal In5 seconds ago
New Job OfferCloudflare10 minutes ago
Daily Email DigestCloudflare1 hour ago
<Table>
  <Table.Header>
    <Table.Row>
      <Table.CheckHead />
      <Table.Head>Subject</Table.Head>
      <Table.Head>From</Table.Head>
    </Table.Row>
  </Table.Header>
  <Table.Body>
    <Table.Row>
      <Table.CheckCell />
      <Table.Cell>Email subject</Table.Cell>
      <Table.Cell>Sender name</Table.Cell>
    </Table.Row>
  </Table.Body>
</Table>

Selected Row

Use variant="selected" on Table.Row to highlight selected rows.

SubjectFromDate
Kumo v1.0.0 releasedVisal In5 seconds ago
New Job OfferCloudflare10 minutes ago
Daily Email DigestCloudflare1 hour ago
<Table.Row variant="selected">
  <Table.CheckCell checked />
  <Table.Cell>Selected row</Table.Cell>
</Table.Row>

Fixed Layout with Column Sizes

For precise control over column widths, set layout="fixed" and use colgroup with col elements.

SubjectFromDate
Kumo v1.0.0 releasedVisal In5 seconds ago
New Job OfferCloudflare10 minutes ago
Daily Email DigestCloudflare1 hour ago
GitLab - New CommentRob Knecht1 day ago
Out of OfficeJohnnie Lappen3 days ago
<Table layout="fixed">
  <colgroup>
    <col />
    <col className="w-[150px]" />
    <col className="w-[150px]" />
  </colgroup>
  <Table.Header>
    <Table.Row>
      <Table.Head>Subject</Table.Head>
      <Table.Head>From</Table.Head>
      <Table.Head>Date</Table.Head>
    </Table.Row>
  </Table.Header>
  <Table.Body>
    {data.map((row) => (
      <Table.Row key={row.id}>
        <Table.Cell>{row.subject}</Table.Cell>
        <Table.Cell>{row.from}</Table.Cell>
        <Table.Cell>{row.date}</Table.Cell>
      </Table.Row>
    ))}
  </Table.Body>
</Table>

Full Example

Complete table with checkboxes, badges, action buttons, and fixed column widths.

SubjectFromDate
Kumo v1.0.0 released
Visal In5 seconds ago
New Job Offer
Cloudflare10 minutes ago
Daily Email Digest
promotion
Cloudflare1 hour ago
GitLab - New Comment
Rob Knecht1 day ago
Out of Office
Johnnie Lappen3 days ago
<Table layout="fixed">
  <colgroup>
    <col style={{ width: "40px" }} />
    <col />
    <col style={{ width: "150px" }} />
    <col style={{ width: "120px" }} />
    <col style={{ width: "50px" }} />
  </colgroup>
  <Table.Header>
    <Table.Row>
      <Table.CheckHead />
      <Table.Head>Subject</Table.Head>
      <Table.Head>From</Table.Head>
      <Table.Head>Date</Table.Head>
      <Table.Head></Table.Head>
    </Table.Row>
  </Table.Header>
  <Table.Body>
    {data.map((row) => (
      <Table.Row key={row.id} variant={row.selected ? "selected" : "default"}>
        <Table.CheckCell checked={row.selected} />
        <Table.Cell>
          <div className="flex items-center gap-2">
            <EnvelopeSimple size={16} />
            {row.subject}
            {row.tags?.map((tag) => <Badge key={tag}>{tag}</Badge>)}
          </div>
        </Table.Cell>
        <Table.Cell>{row.from}</Table.Cell>
        <Table.Cell>{row.date}</Table.Cell>
        <Table.Cell className="text-right">
          <Button variant="ghost" size="sm" shape="square">
            <DotsThree weight="bold" size={16} />
          </Button>
        </Table.Cell>
      </Table.Row>
    ))}
  </Table.Body>
</Table>

API Reference

Table

Root table component. Renders a semantic <table> element.

PropTypeDefaultDescription
layout"auto" | "fixed""auto"-
variant"default" | "selected""default"-
classNamestring-Additional CSS classes
childrenReactNode-Child elements

Table.Header

Table header section. Renders <thead>.

Table.Body

Table body section. Renders <tbody>.

Table.Row

Table row. Supports variant="selected" for highlighting.

PropTypeDefault

No component-specific props. Accepts standard HTML attributes.

Table.Head

Header cell. Renders <th>.

Table.Cell

Body cell. Renders <td>.

Table.CheckHead

Header cell with checkbox for "select all" functionality.

PropTypeDefault

No component-specific props. Accepts standard HTML attributes.

Table.CheckCell

Body cell with checkbox for row selection.

PropTypeDefault

No component-specific props. Accepts standard HTML attributes.

Table.ResizeHandle

Draggable handle for column resizing. Use with TanStack Table or custom resize logic.

TanStack Table Integration

For advanced features like sorting, filtering, and resizable columns, integrate with TanStack Table. The Table component is designed to work seamlessly with TanStack's headless API.

import { flexRender, getCoreRowModel, useReactTable } from "@tanstack/react-table";
import { Table } from "@cloudflare/kumo";

function DataTable({ data, columns }) {
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    columnResizeMode: "onChange",
  });

  return (
    <Table layout="fixed">
      <colgroup>
        {table.getAllColumns().map((column) => (
          <col key={column.id} style={{ width: column.getSize() }} />
        ))}
      </colgroup>
      <Table.Header>
        {table.getHeaderGroups().map((headerGroup) => (
          <Table.Row key={headerGroup.id}>
            {headerGroup.headers.map((header) => (
              <Table.Head key={header.id}>
                {flexRender(header.column.columnDef.header, header.getContext())}
                <Table.ResizeHandle
                  onMouseDown={header.getResizeHandler()}
                  onTouchStart={header.getResizeHandler()}
                />
              </Table.Head>
            ))}
          </Table.Row>
        ))}
      </Table.Header>
      <Table.Body>
        {table.getRowModel().rows.map((row) => (
          <Table.Row key={row.id}>
            {row.getVisibleCells().map((cell) => (
              <Table.Cell key={cell.id}>
                {flexRender(cell.column.columnDef.cell, cell.getContext())}
              </Table.Cell>
            ))}
          </Table.Row>
        ))}
      </Table.Body>
    </Table>
  );
}

Accessibility

Semantic HTML

Table uses semantic <table>, <thead>, <tbody>, <th>, and <td> elements for proper screen reader navigation.

Checkbox Labels

Always provide aria-label for Table.CheckHead and Table.CheckCell to describe their purpose.

Keyboard Navigation

Tab moves focus through interactive elements. Checkboxes respond to Space.