Skip to content

Components

Inline-Editable Tables — Commit Semantics Are the Whole Component

Enter Commits, Escape Reverts, Blur Commits, Failure Rolls Back — Write It Down and Keep It
Written by Aiden Wood Founder and Lead Design Engineer
✏️ ↩️ 🧾

Spreadsheet-style editing is the most requested admin feature and the most commonly half-shipped one. The rendering is easy — a cell swaps to an input on double-click. What separates Airtable from a haunted form is everything around that swap: when the value saves, what cancels it, and what happens when the server says no.

Velocity X's standard-inline-editable-table hardcodes one commit contract and applies it to every cell, because a table where different columns commit differently is worse than no editing at all.

The Money Pattern

The contract: Enter and blur commit, Escape reverts, failure rolls back with the cell re-opened. Optimistic update, remembered previous value:

const commit = async (rowId: string, key: string, next: string) => {
  const prev = rows.find(r => r.id === rowId)?.[key];
  if (next === prev) return setEditing(null);       // no-op edits don't save

  setRows(rs => patch(rs, rowId, key, next));       // optimistic
  setEditing(null);

  try {
    await api.updateCell(rowId, key, next);
  } catch {
    setRows(rs => patch(rs, rowId, key, prev));     // rollback
    setEditing({ rowId, key, draft: next });        // re-open WITH their text
    toast('error', 'Save failed — your edit is preserved');
  }
};

The re-open-with-draft on failure is the line that respects the user: their keystrokes survive the failed request instead of silently reverting. Rollback without re-open is how edits evaporate and nobody trusts the table again.

The Catch

Keyboard reach is what makes it feel like a spreadsheet: Tab commits and moves right, Enter commits and moves down. That means the cell's commit must be synchronous from the keyboard's point of view even though the save is async — commit optimistically, move focus immediately, let rollback interrupt later if it must.

And not every column should be editable. Status fields with side effects (refunds, role changes) belong behind an explicit control with confirmation, not a double-click. Inline editing is for data where a typo is cheap; the component takes an editable flag per column for exactly that line.

The Verdict

Write the commit contract first — Enter, Escape, blur, failure — then build the cells. It's four sentences that decide whether the table feels like a spreadsheet or a trap. The contract's already implemented in Velocity X's Standard Data category, source you own, beside the sortable table it extends.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.