Elyra
Elyra The coding agent e The native code editor Elyra Grove Native local development environment Askr The real server for Laravel & PHP Elyra Framework Rust + Svelte 5 framework for desktop apps Elyra Conductor Local project conductor Elyra SQL Server MySQL-compatible SQL server in Rust Elyra Félagi Agents as teammates on one board Elyra SQL Client Native desktop SQL workbench Elyra SQL Anywhere Replication-ready SQL engine Elyra Sjá SEO & GEO workspace for macOS Elyra DataGrid Server-driven data grid for Laravel
Elyra
Selection, keyboard & clipboard

Selection, keyboard & clipboard

Row selection

const options = { /* ... */ selection: { mode: 'multiple', checkbox: true } };
// selection: { mode: 'single' }

Livewire: public bool $selectable = true;

A checkbox column is added (for multiple), with a header checkbox to select the current page.

grid.toggleSelect(rowId);
grid.isSelected(rowId);
grid.selectAllOnPage();
grid.clearSelection();
grid.selectedIds();

Keyboard navigation & cell selection

The grid is a role="grid" with proper columnheader / gridcell roles, aria-sort, aria-selected, and a roving tabindex.

Key Action
Arrow keys Move the active cell
Home / End First / last cell in the row
Ctrl/⌘ + Home / End First / last cell in the grid
PageUp / PageDown Move up / down by a page (viewport height)
Shift + Arrows Extend a cell range
Click / Shift-Click Set / extend the active range
Space Toggle selection of the active row (selection on)
Ctrl/⌘ + A Select all rows on the page (selection on)
Enter / F2 Edit the active cell (in-cell editing)
Escape Cancel the current edit
Ctrl/⌘ + C Copy the selected range (TSV)
Ctrl/⌘ + V Paste into editable cells (editing enabled)

The active row is highlighted in a quiet grey (.dg-row-active) rather than boxing a single cell, and a multi-cell range is highlighted when you extend a selection. Typing in a filter or editor input is never intercepted by grid navigation.

Programmatic (client core):

grid.setActiveCell(r, c);      // extend? grid.setActiveCell(r, c, true)
grid.moveActive('ArrowDown', /* extend */ false);
grid.isActiveCell(r, c);
grid.inSelectionRange(r, c);
grid.copySelection();          // returns TSV string
await grid.pasteAt(tsvText);   // applies to editable cells from the active cell

copySelection() builds the TSV from the data (not the DOM), so it copies exact values.

Clipboard paste

With editing enabled, Ctrl/⌘ + V reads the clipboard, parses a TSV matrix, and writes it into the editable columns starting at the active cell — one persisted mutation per affected row. Non-editable columns in the paste range are ignored.

Row pinning

Pin rows to the top of the list:

grid.togglePinRow(rowId);
grid.isPinned(rowId);

Pinned rows render first. In the clients a pin button appears in the command column.

Pinning changes the display order, and that order is what row indices mean. copySelection() and pasteAt() resolve the active cell against it (via orderRows()), and the clients render from the same function — so what you copy or paste into is always the row you see at that position.

Accessibility

Keyboard parity is part of the grid's contract, not a coat of paint:

  • Menus (column list, header menu, filter operators) are real <button> elements, so they are reachable by Tab and activated by Enter or Space.
  • Dialogs (row editor, filter builder) are role="dialog" aria-modal="true", move focus inside on open, contain Tab and Shift+Tab, close on Escape, and return focus to whatever opened them.
  • Toggles rendered as spans — the select-all and select-row checkboxes, the sort header, the group collapse control — carry role="button", tabindex="0" and an accessible name, and respond to Enter and Space. They are spans rather than buttons only where a real button would break table layout.
  • Pointer-only affordances (column resize grips, drag-to-group) always have a keyboard equivalent in the column menu, and are marked presentational so they are not announced as controls.

e2e/tests/a11y.spec.ts asserts the focus trap and key activation in Chromium.