Skip to content

Philosophy

Design principles that guide every decision in @ts-zen/datagrid.

Guiding Principles (in priority order)

When two principles conflict, the higher one wins.

1. Must Work Correctly

Correct behavior > API elegance > performance. A datagrid that loses focus or corrupts selection is useless regardless of how fast it is.

2. Performance Is a Functional Requirement

Not premature optimization, but design that doesn't preclude performance:

  • Granular state (don't re-render entire grid for focus change)
  • Selectors/subscriptions instead of prop drilling
  • Virtualization compatibility

3. Ecosystem Composition

Must work with TanStack Table without friction. Same mental model (headless hooks, props getters). Don't force patterns that conflict with how TanStack works.

4. Userland Controls, Library Enables

Never impose concrete implementations. Provide primitives that userland composes. If a pattern is common, provide optional utility — never the only way.

5. Internal Extensibility > Userland Extensibility

Architecture that allows us to add behaviors (drag-and-drop, grouping) without breaking changes. Userland extensibility follows naturally.

6. Minimal API Surface

Every public export is maintenance debt. Prefer one flexible hook over ten specialized ones. Adding APIs is easy, removing them is breaking.

Responsibility Boundaries

DomainTanStack Table@ts-zen/datagridUserland
Column definitionManagesReads (for IDs)Configures
Sorting/filteringManagesConfigures
Row modelManagesReads (for navigation)
Current focusManagesReads (for styling)
Keyboard navigationManagesCan intercept
Selection stateManagesReads, can override
Editing lifecycleManagesReacts (onCommit)
Editing UIManages
ARIA attributesProvides via props gettersApplies
Virtualization— (userland intercepts)Integrates
StylingManages

Non-Goals

Permanent design constraints, not "things we'll do later".

Non-GoalRationale
Provide UI componentsEvery design system has different requirements. Props getters + state are the contract.
Wrap TanStack TableInfinite passthrough maintenance, loses TanStack configuration flexibility.
Handle fetching/mutationOrthogonal, already solved by TanStack Query. We emit events, userland connects.
Touch device support (v1)Touch lacks Ctrl+Click, hover, physical keyboard. Requires different UX patterns.
Opinions on data structureString IDs are the only requirement. How userland structures data is their business.

v1 Scope

In ScopeOut of Scope (Future)Why Deferred
Focus + keyboard navRow drag reorderdnd-kit integration non-trivial
Range selectionColumn drag reorderSame as above
Sync editingAsync validationRace conditions, loading states
CopyCutRequires "pending cut" state
Paste event + parsed dataPaste with auto-insert rowsToo opinionated on mutation
Desktop keyboardTouch device supportDifferent UX patterns needed

Target User

Primary: Developer with existing TanStack Table who wants to add accessible interactivity without rewriting.

Secondary: Someone building a design system who wants behavior primitives to compose.

Success Metric

"I have a working TanStack Table. In <1 hour I have keyboard navigation, selection, inline editing — all accessible, my structure intact."

Released under the MIT License.