---
layout: ~/layouts/MdxDocLayout.astro
title: "Table"
description: "A table component for displaying tabular data with support for selection, row variants, and column sizing."
sourceFile: "components/table"
---

import ComponentExample from "~/components/docs/ComponentExample.astro";
import ComponentSection from "~/components/docs/ComponentSection.astro";
import CodeBlock from "~/components/docs/CodeBlock.astro";
import Heading from "~/components/docs/Heading.astro";
import PropsTable from "~/components/docs/PropsTable.astro";
import {
  TableBasicDemo,
  TableWithCheckboxDemo,
  TableWithCompactHeaderDemo,
  TableSelectedRowDemo,
  TableFixedLayoutDemo,
  TableFullDemo,
} from "~/components/demos/TableDemo";

{/* Demo */}

<ComponentSection>
  <ComponentExample
    code={`<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>`}
  >
    <TableBasicDemo client:visible />
  </ComponentExample>
</ComponentSection>

{/* Installation */}

<ComponentSection>
  <Heading level={2}>Installation</Heading>
  <Heading level={3}>Barrel</Heading>
  <CodeBlock code={`import { Table } from "@cloudflare/kumo";`} lang="tsx" />
  <Heading level={3}>Granular</Heading>
  <CodeBlock
    code={`import { Table } from "@cloudflare/kumo/components/table";`}
    lang="tsx"
  />
</ComponentSection>

{/* Usage */}

<ComponentSection>
  <Heading level={2}>Usage</Heading>
  <CodeBlock
    code={`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>
  );
}`}
    lang="tsx"
  />
</ComponentSection>

{/* Examples */}

<ComponentSection>
  <Heading level={2}>Examples</Heading>

<Heading level={3}>With Checkboxes</Heading>
<p>Add row selection with `Table.CheckHead` and `Table.CheckCell` .</p>
<ComponentExample
  code={`<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>`}
>
  <TableWithCheckboxDemo client:visible />
</ComponentExample>

  <Heading level={3}>Compact Header</Heading>
  <p>
    Use `variant="compact"` on `Table.Header` for a more condensed header style.
  </p>
  <ComponentExample
    code={`<Table>

  <Table.Header variant="compact">
    <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>Email subject</Table.Cell>
      <Table.Cell>Sender name</Table.Cell>
      <Table.Cell>Date</Table.Cell>
    </Table.Row>
  </Table.Body>
</Table>`}
  >
    <TableWithCompactHeaderDemo client:visible />
  </ComponentExample>

  <Heading level={3}>Selected Row</Heading>
  <p>
    Use `variant="selected"` on `Table.Row` to highlight selected rows.
  </p>
  <ComponentExample
    code={`<Table.Row variant="selected">

  <Table.CheckCell checked />
  <Table.Cell>Selected row</Table.Cell>
</Table.Row>`}
  >
    <TableSelectedRowDemo client:visible />
  </ComponentExample>

  <Heading level={3}>Fixed Layout with Column Sizes</Heading>
  <p>
    For precise control over column widths, set <code
      class="rounded bg-kumo-control px-1 py-0.5 text-sm">layout="fixed"</code> and use `colgroup` with `col` elements.
  </p>
  <ComponentExample
    code={`<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>`}
  >
    <TableFixedLayoutDemo client:visible />
  </ComponentExample>

  <Heading level={3}>Full Example</Heading>
  <p>
    Complete table with checkboxes, badges, action buttons, and fixed
    column widths.
  </p>
  <ComponentExample
    code={`<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>`}
  >
    <TableFullDemo client:visible />
  </ComponentExample>
</ComponentSection>

{/* API Reference */}

<ComponentSection>
  <Heading level={2}>API Reference</Heading>

<Heading level={3}>Table</Heading>

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

<PropsTable component="Table" />

<Heading level={3}>Table.Header</Heading>

Table header section. Renders `<thead>`.

<Heading level={3}>Table.Body</Heading>

Table body section. Renders `<tbody>`.

<Heading level={3}>Table.Row</Heading>

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

<PropsTable component="Table.Row" />

<Heading level={3}>Table.Head</Heading>

Header cell. Renders `<th>`.

<Heading level={3}>Table.Cell</Heading>

Body cell. Renders `<td>`.

<Heading level={3}>Table.CheckHead</Heading>
<p>Header cell with checkbox for "select all" functionality.</p>
<PropsTable component="Table.CheckHead" />

<Heading level={3}>Table.CheckCell</Heading>
<p>Body cell with checkbox for row selection.</p>
<PropsTable component="Table.CheckCell" />

  <Heading level={3}>Table.ResizeHandle</Heading>
  <p>
    Draggable handle for column resizing. Use with TanStack Table or
    custom resize logic.
  </p>
</ComponentSection>

{/* TanStack Table Integration */}

<ComponentSection>
  <Heading level={2}>TanStack Table Integration</Heading>
  <p>
    For advanced features like sorting, filtering, and resizable columns,
    integrate with <a
      href="https://tanstack.com/table"
      class="text-kumo-link hover:underline"
      target="_blank"
      rel="noopener noreferrer">TanStack Table</a>. The Table component is designed to work seamlessly with TanStack's
    headless API.
  </p>
  <CodeBlock
    code={`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>
); }`} lang="tsx" />

</ComponentSection>

{/* Accessibility */}

<ComponentSection>
  <Heading level={2}>Accessibility</Heading>

### 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

<kbd>Tab</kbd> moves focus through interactive elements. Checkboxes respond to
<kbd>Space</kbd>.

</ComponentSection>
