VayuUI

Table

A responsive table component with sorting, filtering, and pagination support.

Installation

npx vayu-ui init #one time only
npx vayu-ui add table
npx vayu-ui add -t table #with test case needs

Usage

Table Example

Default Table
A list of your recent invoices.
Invoice
Status
Method
Amount
INV001PaidCredit Card$250.00
INV002PendingPayPal$150.00
INV003UnpaidBank Transfer$350.00
INV004PaidCredit Card$450.00
INV005PaidPayPal$550.00
Total$1,750.00
Table with Selected Row
Invoice
Status
Method
Amount
INV001PaidCredit Card$250.00
INV002PendingPayPal$150.00
INV003UnpaidBank Transfer$350.00
INV004PaidCredit Card$450.00
INV005PaidPayPal$550.00
Table with Sortable Columns
Invoice
Status
Method
Amount
INV001PaidCredit Card$250.00
INV002PendingPayPal$150.00
INV003UnpaidBank Transfer$350.00
INV004PaidCredit Card$450.00
INV005PaidPayPal$550.00
Table with Selectable Rows
Invoice
Status
Method
Amount
INV001PaidCredit Card$250.00
INV002PendingPayPal$150.00
INV003UnpaidBank Transfer$350.00
INV004PaidCredit Card$450.00
INV005PaidPayPal$550.00
Table with Actions
Invoice
Status
Method
Amount
Actions
INV001PaidCredit Card$250.00
INV002PendingPayPal$150.00
INV003UnpaidBank Transfer$350.00
INV004PaidCredit Card$450.00
INV005PaidPayPal$550.00
<Table aria-label="Invoice List">
  <Table.Caption>A list of your recent invoices.</Table.Caption>
  <Table.Head>
    <Table.Row>
      <Table.Header className="w-[100px]">Invoice</Table.Header>
      <Table.Header>Status</Table.Header>
      <Table.Header>Method</Table.Header>
      <Table.Header className="text-right">Amount</Table.Header>
    </Table.Row>
  </Table.Head>
  <Table.Body>
    {invoices.map((invoice) => (
      <Table.Row key={invoice.invoice}>
        <Table.Cell className="font-medium">{invoice.invoice}</Table.Cell>
        <Table.Cell>{invoice.paymentStatus}</Table.Cell>
        <Table.Cell>{invoice.paymentMethod}</Table.Cell>
        <Table.Cell className="text-right">{invoice.totalAmount}</Table.Cell>
      </Table.Row>
    ))}
  </Table.Body>
  <Table.Footer>
    <Table.Row>
      <Table.Cell colSpan={3}>Total</Table.Cell>
      <Table.Cell className="text-right">$750.00</Table.Cell>
    </Table.Row>
  </Table.Footer>
</Table>

Anatomy

import { Table } from 'vayu-ui';

<Table aria-label="Your table description">
  <Table.Caption>Table summary for screen readers.</Table.Caption>
  <Table.Head>
    <Table.Row>
      <Table.Header>Column A</Table.Header>
      <Table.Header>Column B</Table.Header>
    </Table.Row>
  </Table.Head>
  <Table.Body>
    <Table.Row>
      <Table.Cell>Data A1</Table.Cell>
      <Table.Cell>Data B1</Table.Cell>
    </Table.Row>
  </Table.Body>
  <Table.Footer>
    <Table.Row>
      <Table.Cell>Total</Table.Cell>
      <Table.Cell>$100.00</Table.Cell>
    </Table.Row>
  </Table.Footer>
</Table>;
  • Table — Root container. Wraps a native <table> inside a scrollable container with border and shadow.
  • Table.Caption — Accessible caption element. Supports visuallyHidden to hide visually while remaining readable by screen readers.
  • Table.Head<thead> section containing column header rows.
  • Table.Body<tbody> section containing data rows. Supports empty prop to enable aria-live announcements.
  • Table.Footer<tfoot> section for summary or totals rows.
  • Table.Row<tr> row element. Supports selectable and selected for interactive row selection.
  • Table.Header<th> header cell with sort icon support via sortable and aria-sort props.
  • Table.Cell<td> data cell with support for rowSpan, colSpan, and accessibility indexing.

Accessibility

  • Keyboard Support:
    • Tab — Moves focus to the next focusable element. Selectable rows (selectable) receive tabIndex={0}.
    • Enter / Space — Activates a selectable row (selection handling is user-implemented).
    • Enter / Space — Activates a sortable header column (sort handling is user-implemented).
  • ARIA Attributes:
    • aria-label on Table provides an accessible name for the table.
    • aria-describedby on Table references an external description element.
    • aria-colcount and aria-rowcount on Table for large or virtualized tables.
    • aria-sort on Table.Header reflects the current sort state (ascending, descending, none).
    • aria-selected on Table.Row indicates selection state when selectable is set.
    • aria-rowindex on Table.Row for row position in large tables.
    • aria-colindex on Table.Header and Table.Cell for column position.
    • aria-live="polite" on Table.Body when empty is true, announcing empty state changes.
    • headers on Table.Cell links to associated header cell IDs.
    • Sort indicator icons are marked aria-hidden="true" since state is conveyed via aria-sort.
  • Focus Behavior:
    • Selectable rows show a visible focus ring on focus-visible.
    • Sortable headers show a visible focus ring on focus-visible.
    • Focus indicators use the design system focus token (ring-focus) with offset.

Screen reader behavior

When a screen reader encounters the table, it announces the accessible name (from aria-label or Table.Caption) and describes the table structure. The screen reader reads column headers as the user navigates across rows, using the scope="col" attribute on Table.Header to associate headers with their columns. For sortable columns, the screen reader announces the current sort direction via aria-sort. Selectable rows announce their selection state through aria-selected. When the table body is empty and empty is set, the aria-live="polite" region announces content changes. For large tables using aria-rowcount and aria-colcount, the screen reader communicates the total table dimensions even when not all rows are rendered.

Component Folder Structure

Table/
├── Table.tsx          # Root component with compound component composition
├── TableCaption.tsx   # Caption with visually-hidden support
├── TableHead.tsx      # <thead> section element
├── TableBody.tsx      # <tbody> section with empty state aria-live
├── TableFooter.tsx    # <tfoot> section element
├── TableRow.tsx       # <tr> row with selectable and selected state
├── TableHeader.tsx    # <th> header cell with sort icon logic
├── TableCell.tsx      # <td> data cell
├── types.ts           # TypeScript type definitions
├── index.ts           # Re-exports all components and types
└── README.md          # Component usage reference

Props

Table

PropTypeDefaultDescription
childrenReactNodeTable sections (Caption, Head, Body, Footer).
classNamestringAdditional CSS classes.
aria-labelstringAccessible name for the table.
aria-describedbystringID of an element describing the table.
aria-colcountnumberTotal column count for virtualized tables.
aria-rowcountnumberTotal row count for virtualized tables.

Table.Caption

PropTypeDefaultDescription
childrenReactNodeCaption content.
classNamestringAdditional CSS classes.
visuallyHiddenbooleanfalseHide visually but keep accessible to screen readers.

Table.Head

PropTypeDefaultDescription
childrenReactNodeHeader rows.
classNamestringAdditional CSS classes.

Table.Body

PropTypeDefaultDescription
childrenReactNodeData rows.
classNamestringAdditional CSS classes.
emptybooleanfalseEnable aria-live for empty state announcements.

Table.Footer

PropTypeDefaultDescription
childrenReactNodeFooter rows.
classNamestringAdditional CSS classes.

Table.Row

PropTypeDefaultDescription
childrenReactNodeRow cells.
classNamestringAdditional CSS classes.
aria-rowindexnumberRow position for large tables.
selectedbooleanfalseWhether the row is currently selected.
selectablebooleanfalseEnable keyboard focus and selection cues.

Table.Header

PropTypeDefaultDescription
childrenReactNodeHeader cell content.
classNamestringAdditional CSS classes.
scope"row" | "col" | "rowgroup" | "colgroup""col"Scope of the header cell.
aria-colindexnumberColumn position for accessibility.
aria-sort"ascending" | "descending" | "none" | "other"Current sort direction.
sortablebooleanfalseShow sort indicator and enable interaction.

Table.Cell

PropTypeDefaultDescription
childrenReactNodeCell content.
classNamestringAdditional CSS classes.
aria-colindexnumberColumn position for accessibility.
aria-rowindexnumberRow position for accessibility.
headersstringID of associated header cells.

On this page