Inline Editable Grid
A spreadsheet-feel data grid: one spring-loaded selection ring, edit in place by typing or Enter, typed columns with inline validation, a totals footer whose digits roll, undo, copy and paste.
DOM + CSS0 deps1 file · 34 KB TSXreduced-motion aware
Props
"use client";
import {
useEffect,
useId,
useMemo,
useRef,
useState,
useSyncExternalStore,
type ClipboardEvent,
type KeyboardEvent,
type ReactNode,
} from "react";
export type GridColumnType = "text" | "number" | "currency";
export type GridColumn = {
key: string;
// ---------------------------------------------------------------
// Full source available with a viberdy Pro subscription.
// https://viberdy.dev/pricing
// ---------------------------------------------------------------
}Details
About this component
A data grid you can drive without the mouse. Cells are plain elements until you edit one: the grid itself holds focus and points at the active cell with aria-activedescendant, so the arrow keys are always free to move. The selection is one absolutely positioned ring measured in layout pixels from the active cell and animated with an overshooting curve, so it travels between cells instead of snapping, and it stretches to the next cell's size. Typing starts an edit that replaces the value, Enter or F2 edits with the value selected, Enter commits and moves down, Tab commits and moves right, Escape throws the draft away. Columns have types (text, number, currency): number cells validate live, show an inline tooltip beside the ring (numbers only, whole numbers, minimum and maximum) and refuse to commit until fixed. A committed cell flashes, calculated columns (a compute function over the row) update and flash with it, and the totals footer rolls each changed digit like an odometer. Ctrl or Cmd Z undoes the last commit and moves the ring to it, Shift+Z or Ctrl Y redoes, Ctrl C copies the cell and Ctrl V pastes into it. The first column is pinned and the body scrolls sideways on a phone; tap a cell to select it and tap again to edit. Rows are strings, so existing data and the onChange callback keep their shape; onCommit adds the individual change.
Curator’s note
Rebuilt in October: the old grid was a table with a border on the active cell. This one is a proper spreadsheet surface, with a single selection ring that springs between cells, typed columns, validation, rolling totals and undo.

