Prepared Docs

Prepared Docs

⌘K

    Loading navigation…

User

  1. Blocks
  2. Data Table
  3. Usage

Data table

Usage

Overview

DataTable from @prepared911/ui-data-table is the system component for interactive tabular data. It pairs a scrollable grid with a filter region, a selection model, per-row menus, an optional expansion region, and a floating toolbar for bulk work. The mental model is "spreadsheet-like power with guardrails": operators refine the view, then act on many rows at once without leaving the table.

It is the default choice for incident lists, call queues, staff rosters, and any list view where users scan dense information, sort and filter aggressively, and invoke actions across a selection.

When to use

  • Large or server-driven lists (pagination, cursor, unbounded rows) with sort, filter, and search at operational scale.
  • Bulk selection and floating-toolbar actions across many rows.
  • Row actions via compact Menu columns and optional expansion for detail snippets.
  • Drawer-adjacent layouts where horizontal scroll stays usable beside a detail panel (ResizableDrawer).

Large or server-driven datasets

Use a DataTable when the list is unbounded, paginated, or served from a cursor—dispatch incident history, call records, alert queues. Client sort/filter suits only bounded collections of a few hundred rows; beyond that, server-driven sort, filter, and pagination keep the grid responsive.

Bulk workflows with selection

Use multiSelect when operators need to act on many rows at once (assign, update status, export). The floating toolbar reveals itself when selection is non-empty and lists applicable bulk actions. Disable selection on rows that cannot participate, don't hide them.

Row-scoped actions

Per-row actions (open, assign, archive) belong in a compact menu column, rendered with Menu from @prepared911/ui-core through the row's action config. Keep the menu short (six items or fewer) and group with separators.

Drawer-adjacent layouts

When a detail drawer shares horizontal space with the grid, the table reserves scroll width so users still reach columns that sit under the drawer. Pair with ResizableDrawer for widths the operator can control.

When not to use

  • Small, static tables (≤ 20 rows, no interaction). Use a plain Table for light display of known-size data.
  • Generic layout. DataTable is for tabular content; don't reach for it as a two-column layout wrapper.
  • Read-only dashboards without filtering, selection, or actions. A simpler table keeps the bundle small and reduces visual noise.
  • Heavily nested hierarchies. Use a tree/outline pattern (or a dedicated component) rather than stretching expandable rows.

Composition

DataTable accepts column configs and optional slots:

  • Columns. Each column config defines the header, cell renderer, sort key, filter integration, and alignment. Memoize the column array; inline redefinitions remount cells on every render.
  • Filter region. Segmented controls, search, column visibility, category filters, quick filters, applied-chip row, and clear.
  • Floating toolbar. Reveals on selection with bulk-action buttons.
  • Expanded row. Optional disclosure under each row for occasional detail.
  • Pagination or infinite scroll. Choose one per view—don't mix.
  • Persistent row and selection chrome. Pass showCheckboxes together with multiSelect, or showActionMenuTriggers together with actionMenu, when checkboxes or kebab triggers should remain visible without hovering (touch-heavy or sparse-hover layouts). The flags mirror to data-show-checkboxes and data-show-action-menu-triggers on the table root when active.
  • Fluid column sizing. Set fluidWidth when percentages and flex weights should dominate: fixed px/rem column sizes are folded into equal flex alongside other flex columns, and table minWidth / column maxWidth do not constrain layout. Root gets data-fluid-width. Omit for legacy pixel-stable layouts.

Content guidelines

  • Column headers. Short, sentence-case (or match the adjacent app conventions). Align with how the same entity is named in nearby views.
  • Actions. Verb-first ("Assign", "Open", "Remove"). Destructive actions use destructive styling and confirm for irreversible work.
  • Empty vs error. When the grid is empty, explain why ("No results for these filters" vs "No incidents yet") and offer a recovery path. On error, pair a retry action with the last failure message.
  • Counts and pluralization. Pluralize selection counts and pagination strings via formatMessage; "1 incident" / "24 incidents" must localize cleanly.
  • Density. Prefer consistent row height within a view. If cells have varying content (multi-line, avatars), truncate and make the long form accessible via hover or a row expand.

Behavior and states

Sort

Default sort is visually explicit (arrow + state). Sort changes trigger onSortingChange; for server-driven data, debounce and cancel stale requests. Announce the new sort direction in a polite live region so assistive tech users know the grid reordered.

Filter

Debounce search input (~300 ms) before firing server requests. Make applied filters visible in a chip row above the table, and give a single "Clear all" control that respects defaults. Never hide the only applied-filter indicator behind a tooltip.

When the filter region includes a reorderable columns menu, pass columnOrder to both Filter and DataTable so menu order and grid headers stay aligned. Visibility-only integrations can omit columnOrder; the columns menu then toggles visibility without drag handles. Column-order ids follow TanStack Table: explicit id, then accessorKey with dots replaced by underscores, then a string header.

Derive the initial reorderable order from the same visibility options passed to Filter; keep that order as the single source for both the menu and DataTable.

Loading

Show a skeleton on first paint; for partial refresh (paging, filter), use an inline loading indicator rather than replacing the grid. Keep the column header row stable so the eye doesn't reset.

Selection

Decide up front whether selection clears when the user pages; document the choice in the toolbar copy ("25 selected across all pages" vs "25 selected on this page"). select-all spanning pages should spell it out explicitly.

Bulk actions

Guard destructive bulk work with a confirm step. Stream progress when the job is long (a Snackbar update with a running count beats a silent spinner). Handle partial failure by reporting the count that succeeded and the count that didn't.

Drawer interaction

When a Drawer is open, horizontal scroll should still expose obscured columns—verify at the narrowest layout your product supports. Pair with the columnVisibility config so operators can hide columns they're not reviewing.

Best practices

Do

  • Put the most important identifiers in the leading columns; keep numeric columns right-aligned.
  • Memoize column definitions with useMemo and avoid heavy work inside cell renderers.
  • Limit action menus to a small, coherent set and group with separators.
  • Show destructive bulk actions with a confirm step, never as a silent one-click.

Don't

  • Don't use DataTable as a generic layout wrapper.
  • Don't rely on color-only status encoding; pair every colored state with text or an icon.
  • Don't offer bulk actions that contradict row-level disabled rules without explaining why.
  • Don't swap paginate and infinite-scroll in the same view—pick one.

Accessibility

Full semantic table structure, sortable headers with aria-sort, and keyboard paths for every toolbar and row action are covered in the Accessibility pages. The big rules: don't move focus unexpectedly after refresh, announce filter and sort changes politely, and keep the selection model visible in both the row and the toolbar.

Related Components

  • Table: static semantic HTML table for small, read-only data.
  • Drawer: the detail panel that pairs with DataTable.
  • Toolbar: the floating strip the bulk toolbar is built on.
  • Pagination: the design-system pagination component used below the table.

Previous

AI Elements / Accessibility

Next

Data Table / API and Development

On this page

Overview
When to use
Large or server-driven datasets
Bulk workflows with selection
Row-scoped actions
Drawer-adjacent layouts
When not to use
Composition
Content guidelines
Behavior and states
Sort
Filter
Loading
Selection
Bulk actions
Drawer interaction
Best practices
Accessibility
Related Components