Skip to content

DataTable with bulk actions

An interactive grid for records people select, sort and open: a sticky header, numeric and action columns, and a selected row marked with a tint and a leading rule. BulkActionBar sits above it and acts on the selection.

  • DataTable
  • BulkActionBar

PreviewLink to the section Preview

Live in all three themes. Everything here is interactive.

Light theme, DataTable with bulk actions

InvoiceClientStatusTotalActions
INV-1042Northwind TradersPaid€1,240.00
INV-1043Contoso Pharmaceuticals and Laboratory SuppliesDue€86.50
INV-1044FabrikamOverdue€4,310.00
INV-1045Tailspin ToysPaid€512.75
INV-1046Wide World ImportersDue€2,075.00

Dark theme, DataTable with bulk actions

InvoiceClientStatusTotalActions
INV-1042Northwind TradersPaid€1,240.00
INV-1043Contoso Pharmaceuticals and Laboratory SuppliesDue€86.50
INV-1044FabrikamOverdue€4,310.00
INV-1045Tailspin ToysPaid€512.75
INV-1046Wide World ImportersDue€2,075.00

High contrast theme, DataTable with bulk actions

InvoiceClientStatusTotalActions
INV-1042Northwind TradersPaid€1,240.00
INV-1043Contoso Pharmaceuticals and Laboratory SuppliesDue€86.50
INV-1044FabrikamOverdue€4,310.00
INV-1045Tailspin ToysPaid€512.75
INV-1046Wide World ImportersDue€2,075.00

UsageLink to the section Usage

tsx
import { DataTable, BulkActionBar } from '@skribly/ui/data'
tsx
<BulkActionBar aria-label="Actions for selected invoices" count={count}
  countLabel={(n) => `${n} selected`} onClear={clear} clearLabel="Clear selection">
  <Button variant="danger" size="sm" onPress={remove}>Delete</Button>
</BulkActionBar>
<DataTable
  aria-label="Invoices"
  className="max-h-72"
  columns={columns}
  items={invoices}
  rowKey={(i) => i.id}
  selectionMode="multiple"
  selectedKeys={selected}
  onSelectionChange={setSelected}
  sortDescriptor={sort}
  onSortChange={setSort}
/>

Every label is a prop, so the app passes its own words in its own language. See no built-in text.

AccessibilityLink to the section Accessibility

  • Tab enters the grid once; arrow keys move between cells, Space toggles a row, Enter opens it when onRowAction is set, and typing jumps to a row.
  • Column headers sort with Enter and React Aria announces the new order.
  • Row checkboxes are named after the row header.
  • The bulk bar is a toolbar with one tab stop and arrow keys between its actions; its buttons disable while nothing is selected, and focus moves to the count when an action empties the selection.

This demo runs through axe in all three themes on every test run. See what the tests check.

Search this site

Arrows move through the results, Enter opens one, Esc closes. Ctrl K /