GitHub

Data Cell

A lightweight editable cell for scalar document data: text, numbers, booleans, dates, times, and date-times.

Data Cell is the primitive for dense editable data surfaces. It renders the same compact cell shell for display and edit states, keeps editable cells display-only until interaction, and normalizes input behavior for common JSON scalar types.

Kind
Display
Edit
Text
CHECKCARD PURCHASE
Number
-108,3
Integer
42
Boolean
Date
12/06/2026
Time
13:25:37
Date Time
12/06/2026, 13:25
Enum
approved

Installation

pnpm dlx shadcn@latest add @retab/data-cell

Usage

import { DataCell } from "@/components/ui/data-cell"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
 
<DataCell kind="number" value={-108.3} />
 
<DataCell
  kind="number"
  editable
  value="-108.3"
  onCommit={(value, meta) => {
    // value is number | null for numeric cells
    // meta.isValid distinguishes invalid input from an empty nullable value
  }}
/>
 
<DataCell
  kind="text"
  editable
  value="Committed"
  draftValue={draft}
  onDraftValueChange={setDraft}
  onCommit={(value) => {
    // value is string | null
  }}
/>
 
const statusOptions = ["pending", "approved", "rejected"]
 
{isEditing ? (
  <Select value={status} onValueChange={setStatus}>
    <SelectTrigger className="h-8 min-h-8 w-full rounded-md border-transparent bg-transparent px-2 text-sm shadow-none">
      <SelectValue placeholder="Select..." />
    </SelectTrigger>
    <SelectContent>
      {statusOptions.map((option) => (
        <SelectItem key={option} value={option}>
          {option}
        </SelectItem>
      ))}
    </SelectContent>
  </Select>
) : (
  <DataCell kind="text" value={status} editable />
)}
 

API Reference

PropTypeDefault
kindDataCellKind-
valueDataCellValueundefined
mode"display" | "edit" | "auto""auto" when editable, otherwise "display"
editablebooleanfalse
disabledbooleanfalse
namestringundefined
placeholderstring"—"
dateTimeZone"local" | "preserve" | "utc""local"
formatValue(value, meta) => React.ReactNodeundefined
draftValuestringundefined
autoFocusbooleanfalse
onDraftValueChange(value: string, meta: DataCellValueMeta) => voidundefined
onCommit(value, meta) => void typed by kindundefined

DataCell forwards standard data-*, ARIA, event, and style props to the rendered cell. In auto mode, it renders the display cell first and only mounts the edit control while hovered, focused, or explicitly activated. Number and integer edit cells intentionally use native type="number" inputs and keep the raw draft text separate from parsed commit metadata.

onCommit is discriminated by kind: number and integer cells commit number | null, boolean cells commit boolean, and text/date/time/date-time cells commit string | null.

DataCell only normalizes scalar input values. Schema policy belongs in the adapter: nullable fields can turn empty null commits into stored null, required numeric fields can ignore meta.isValid === false, and date-time fields can opt into explicit timezone preservation with dateTimeZone. Enum fields use the same scalar kind as their values, usually text, and keep option validation or select controls in the schema adapter. Keep the enum adapter as a display cell until hover, focus, or activation, then mount the real select.

Source

data-cell.tsx