react-datatable
Guides

Add row preview

Use this guide when users need to inspect row details without leaving the table.

What row preview is

Row preview opens a lightweight detail panel while the user stays in the table.

It works well for quick inspection, comparison, and scanning supporting context before deciding whether to open the full record.

Use rowActions.onOpenRow instead when the next step should leave the table, enter an edit flow, or route to a dedicated detail page.

Media placeholder: Floating row preview beside a realistic table

Show a table with one row active and its preview panel open beside the grid so the in-context inspection model is obvious.

Add a preview renderer

Preview is available when you provide preview.renderPreview.

renderPreview can return any React component you want.

function CustomerPreview({ customer, onClose }: { customer: Customer; onClose: () => void }) {
  return (
    <div>
      <h3>{customer.name}</h3>
      <p>{customer.email}</p>
      <button onClick={onClose}>Close</button>
    </div>
  )
}

<Datatable
  tableKey="customers"
  data={rows}
  columns={columns}
  getRowId={(row) => row.id}
  preview={{
    renderPreview: ({ row, close }) => (
      <CustomerPreview customer={row} onClose={close} />
    ),
  }}
/>

The renderer receives row, rowId, and close().

Keep the preview focused on inspection. If it starts to need routing, multi-step workflows, or heavy mutation, it is probably becoming a full detail page.

[!NOTE] Screenshot placeholder: floating row preview panel open, repositioned, and tied to the active row in a realistic table.

Configure the floating panel

The built-in preview surface is a floating panel rendered above the table.

<Datatable
  tableKey="customers"
  data={rows}
  columns={columns}
  getRowId={(row) => row.id}
  preview={{
    floating: {
      draggable: true,
      storageKey: "customers-preview",
    },
    renderPreview: ({ row, close }) => <CustomerPreview customer={row} onClose={close} />,
  }}
/>

The current preview options are:

  • floating.draggable — lets users move the panel out of the way; defaults to true
  • floating.storageKey — stores the panel position in sessionStorage
  • floating.width — preferred panel width, clamped to the viewport
  • floating.height — preferred panel height, clamped to the viewport
  • followRowHoverWhenOpen — when true, hovering a different row moves the open preview to that row

If you omit floating.storageKey, the preview reuses the top-level tableKey for position storage.

[!NOTE] Screenshot placeholder: draggable preview panel moved away from the grid, making the floating behavior and preserved position feel intentional instead of accidental.

Preview behavior

When preview is configured:

  • clicking a data row opens preview for that row
  • Space toggles preview for the active data row
  • Esc closes preview before clearing other interaction state
  • keyboard movement can carry preview along with the active row
  • onTogglePreviewRow can observe open/close events for analytics or side effects

If you also provide rowActions.onOpenRow, preview remains the in-table inspection path and open-row remains the deeper navigation path.

[!NOTE] Screenshot placeholder: row preview open beside a visible “open full record” affordance so the distinction between lightweight preview and deeper navigation is obvious.

Verify row preview before you move on

Before you continue, confirm that:

  • the preview content answers a real inspection need
  • click and keyboard preview behavior match the intended workflow
  • Space toggles preview on the active row
  • Esc closes preview cleanly
  • the floating panel can be moved when it would otherwise cover important data
  • the panel position is only persisted when a stable storageKey is appropriate
  • width and height overrides still behave well at smaller viewport sizes
  • full row navigation still has a clear, separate path

On this page