gridcn1.2.2
RecipesUI patterns

Open a detail panel from a row

Show the active row in a side panel that stays open while you move through the grid.

A side panel that shows one record needs two things: a gesture that opens it and state that holds the row. The panel in the demo does not block the grid. It slides in from the right and shows the active row. Keyboard focus stays in the grid, so the arrow keys keep moving the active cell and the panel follows. Click a cell, or press Ctrl+Shift+Enter on the active cell:

Click a cell, or press Ctrl+Shift+Enter on the active cell, to show its row. The panel follows the active cell while you move with the arrow keys. Escape closes it when focus is inside the panel.

Name
Email
Role
Active
Silent Tiger
user0@example.com
Viewer
Quick Lion
user1@example.com
Viewer
Swift Wolf
user2@example.com
Manager
Eager Lion
user3@example.com
User
Eager Tiger
user4@example.com
Viewer
Silent Wolf
user5@example.com
User
Swift Lion
user6@example.com
Viewer
Eager Lion
user7@example.com
Manager
Eager Eagle
user8@example.com
Editor
Bold Tiger
user9@example.com
Editor
Bold Bear
user10@example.com
User
Swift Wolf
user11@example.com
Manager
Swift Bear
user12@example.com
Viewer
Eager Wolf
user13@example.com
Editor
Swift Eagle
user14@example.com
Viewer
Quick Lion
user15@example.com
Manager
Bold Wolf
user16@example.com
Editor
Swift Eagle
user17@example.com
Admin
Eager Eagle
user18@example.com
Manager
Eager Bear
user19@example.com
Editor
Silent Lion
user20@example.com
Manager
Silent Tiger
user21@example.com
Manager
Eager Tiger
user22@example.com
Manager
Silent Lion
user23@example.com
Admin
Bold Eagle
user24@example.com
Admin
Bold Lion
user25@example.com
Viewer
Quick Tiger
user26@example.com
Viewer
Bold Eagle
user27@example.com
Editor
Swift Tiger
user28@example.com
Editor
Silent Lion
user29@example.com
Viewer

Open the panel

The panel is an aside beside the grid. It has role="complementary" and an aria-label, and it carries no modal semantics: no overlay, no focus trap, no scroll lock. A CSS transform slides it in. While it is closed, the inert attribute removes it from the tab order and the accessibility tree.

Use a dialog only when the task must stop until the user answers. A dialog traps focus and blocks the grid, so it breaks the flow of moving down a list.

Mouse

onCellClick fires for a click on any data cell. The checkbox toggle fires onCellClick too, so compare ctx.columnId to skip the checkbox column:

<DataGrid
  data={orders}
  columns={columns}
  onCellClick={(ctx) => {
    if (ctx.columnId !== "selected") setPanelOpen(true);
  }}
/>

A click on the row marker selects the row and fires no click callback. Read onSelectionChange with details.getRowIds() to react to it.

Keyboard

Enter, F2, and a double-click edit the cell, so the open gesture needs its own key. A custom command reads the active row from ctx.row, and keymap binds it. Declare the command name once so keymap accepts it. Ctrl+Enter is taken by scrollActiveIntoView, so the example binds mod+shift+Enter:

declare module "@/components/data-grid/types" {
  interface GridActions {
    openRow: true;
  }
}

const commands = {
  openRow: {
    label: "Open row",
    when: (ctx) => ctx.row !== undefined,
    run: () => setPanelOpen(true),
  },
};

<DataGrid
  data={orders}
  columns={columns}
  commands={commands}
  keymap={{ openRow: ["mod+shift+Enter"] }}
/>

when runs the command only while a cell is active. After Escape the selection is empty, but the active cell stays, so the command still opens the panel.

Follow the active row

onActiveCellChange fires each time the active cell moves. The panel reads next.rowId and clears itself on null:

<DataGrid
  data={orders}
  columns={columns}
  onActiveCellChange={(next) => setPanelRowId(next?.rowId ?? null)}
/>

Look the row up by id in your own data. The event carries the cell reference, not the row.

Focus and Escape

Focus stays in the grid while the panel is open, so Escape in the grid keeps its grid meaning. Escape closes the panel when focus is inside it, for example after Tab onto the close button. Closing the panel returns focus to the grid.

On this page