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
| Domain | TanStack Table | @ts-zen/datagrid | Userland |
|---|---|---|---|
| Column definition | Manages | Reads (for IDs) | Configures |
| Sorting/filtering | Manages | — | Configures |
| Row model | Manages | Reads (for navigation) | — |
| Current focus | — | Manages | Reads (for styling) |
| Keyboard navigation | — | Manages | Can intercept |
| Selection state | — | Manages | Reads, can override |
| Editing lifecycle | — | Manages | Reacts (onCommit) |
| Editing UI | — | — | Manages |
| ARIA attributes | — | Provides via props getters | Applies |
| Virtualization | — | — (userland intercepts) | Integrates |
| Styling | — | — | Manages |
Non-Goals
Permanent design constraints, not "things we'll do later".
| Non-Goal | Rationale |
|---|---|
| Provide UI components | Every design system has different requirements. Props getters + state are the contract. |
| Wrap TanStack Table | Infinite passthrough maintenance, loses TanStack configuration flexibility. |
| Handle fetching/mutation | Orthogonal, 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 structure | String IDs are the only requirement. How userland structures data is their business. |
v1 Scope
| In Scope | Out of Scope (Future) | Why Deferred |
|---|---|---|
| Focus + keyboard nav | Row drag reorder | dnd-kit integration non-trivial |
| Range selection | Column drag reorder | Same as above |
| Sync editing | Async validation | Race conditions, loading states |
| Copy | Cut | Requires "pending cut" state |
| Paste event + parsed data | Paste with auto-insert rows | Too opinionated on mutation |
| Desktop keyboard | Touch device support | Different 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."