Skip to content

Keyboard navigation

The grid is built to be driven without a mouse: one focused cell, arrows to move, a handful of spreadsheet keys, and menus that are ordinary shadcn menus. This page is the complete list.

Chloe TanakaSalesInvitedFree1$0.00Sep 17, 2024
Nia SilvaSupportInvitedPro2$24.00Jun 27, 2023
Zara SilvaGrowthPausedPro3$36.00Jun 10, 2026
Elias MüllerDataChurnedPro2$0.00Feb 3, 2024
Leila KimPlatformPausedEnterprise48$3,792.00Mar 24, 2023
Mia NguyenDataChurnedFree1$0.00Oct 30, 2024
Sofia PrabhakaranSalesInvitedTeam20$580.00Aug 27, 2026
Nia IyerSalesActivePro4$48.00Feb 2, 2023
0 of 50 row(s) selected.
Page 1 of 7

Click a cell, then try:↑ ↓ ← → moveShift + ↑ ↓ ← → extend the rangeHome / End first / last columnPageUp / PageDown a screen of rowsEnter or F2 editSpace select the row⌘A select every cell⌘C copyEsc collapse the range

Tab reaches the toolbar, then the column headers (each sortable header is a button), then the body, then the pager. The body uses a roving tabindex: only the focused cell is a tab stop, and until a cell has been focused there is none. The first time, press Tab to a header and then any arrow key, or click a cell; after that Tab returns to the last focused cell.

⌘ below is Ctrl on Windows and Linux.

Keys What happens
↑ ↓ ← → Move the focused cell. The range collapses to it.
Shift+↑ ↓ ← → Extend the range one cell, keeping its anchor.
Home / End First / last data column in the current row.
⌘Home / ⌘End First column of the first row / last column of the last row on the current page.
PageUp / PageDown Up / down by one screen of rows (viewport height ÷ row height, minus one), within the current page.
Enter or F2 Open the editor on an editable cell; on an expandable row with no editor, toggle it.
Space Toggle the focused row’s selection (with its sub-rows). Announces the count.
⌘A Select every cell. Announces the count.
⌘C Copy the selected cells as TSV. Announces “Copied n cells”.
Esc Collapse a range to the focused cell. In fullscreen with nothing selected, leave fullscreen.

Movement skips the checkbox, expander, row-number and actions columns at the ends of a row, and scrolls the cell into view, including rows that are not yet rendered in a virtualized grid.

Keys What happens
Enter Commit and move down one cell.
Shift+Enter Commit and stay. In a textarea: insert a line break.
Tab / Shift+Tab Commit and move right / left.
Esc Cancel: close the editor and keep the old value.
arrows, Home, End Belong to the input (move the caret).

A select editor opens its list at once: arrows move, Enter chooses and commits, Esc cancels. A checkbox commits as soon as it is toggled. See inline editing for what happens on commit.

Keys What happens
Tab Focus the next header’s sort button, then its filter and menu buttons (they appear on focus).
Enter or Space on the title Toggle the sort: ascending, descending, off.
Shift+Enter on the title, or Shift-click Add the column to a multi-column sort instead of replacing it.
Enter on the ⋯ button Open the column menu: sort, filter, pin, move, group, fit, hide.
Enter on the filter button Open the filter popover; its inputs take the usual keys.
right-click on a header Open the column menu with the pointer.

Inside a menu (Base UI): ↑ ↓ move, Enter activates, Esc closes and returns focus to the trigger. Move left and Move right in the column menu are the keyboard route to reordering; dragging a header has no keyboard equivalent.

Every control is a button, input or select with its normal keys. In the pager, type a page number in the “Go to page” field and press Enter. The search box clears on Esc.

  • After a commit or cancel, focus returns to the cell, or to the cell Enter or Tab moved to.
  • The grid only moves focus when focus is already inside it; changing the focused cell from code while you are typing in the search box does not steal it.
  • In a virtualized grid, moving to a row that is not rendered scrolls it into view first and focuses it once it exists.
  • Opening a menu or popover moves focus into it; closing it returns focus to the trigger.

A visually hidden aria-live="polite" region in the grid root announces, using the labels:

Event Text
sort toggled from the header Name: Sort ascending / … Sort descending / … Clear sort
row selected with Space, or ⌘A labels.selected(n): “3 selected”
cells or rows copied labels.copied(n): “Copied 12 cells”

Call useDataGridUi().announce(message) from your own parts to speak through the same region.