TanStack Table
Reference Repositories
- TanStack Table - Headless table state and row models
- Svelte - Svelte 5 component and reactivity model
Upstream Grounding
When TanStack Table adapter APIs, row models, controlled state, sorting, filtering, pagination, or Svelte rendering helpers affect correctness, ask DeepWiki a narrow question against TanStack/table. Verify against the installed @tanstack/svelte-table and @tanstack/table-core versions.
This skill is for UI table state. Use yjs for Epicenter store table storage, and svelte for reading rows into a component.
Local API Baseline
Epicenter currently uses @tanstack/svelte-table with:
import {
createTable as createSvelteTable,
FlexRender,
renderComponent,
} from '@tanstack/svelte-table';
import type { ColumnDef } from '@tanstack/table-core';
Table Construction Rules
- Always set
getRowId for persisted or local-first rows. Do not rely on array index identity.
- Keep
data referentially stable. Avoid creating a fresh array in the table options getter unless the table is intentionally rebuilt.
- Define columns with
satisfies ColumnDef<Row>[].
- Give accessor columns stable ids, especially when sorting, hiding, or persisted preferences are involved.
- Use
renderComponent for reusable header and cell components.
- Include only row models the UI uses: core always, sorted/filter/pagination only when the surface needs them.
Controlled State
- Control only state Epicenter owns externally, such as sorting, global filter, column visibility, row selection, or pagination.
- If an
onXChange handler is present, the matching state.get x() must also be present.
- Keep state ownership in one component or handle. Do not split sorting, filters, and pagination across unrelated stores without a reason.
Rendering
- TanStack Table owns row, column, and cell state.
@epicenter/ui/table owns semantic table markup and styling.
- Render headers and cells with
FlexRender.
- Key rows by
row.id and cells by cell.id.
- Empty states stay in
ui-design: when row count is zero, render Empty.Root in the table body or surrounding panel.
- Add explicit keyboard behavior for clickable rows. A click handler alone is not a row interaction model.
- Use TanStack Virtual separately for large lists. Do not treat virtualization as a built-in table feature.
1---2name: tanstack-table3description: Apply TanStack Table UI-state patterns for Svelte data tables, including columns, rendering, sorting, filtering, pagination, and row identity. Use when building or reviewing data-table UI, not Epicenter workspace storage tables.4---56# TanStack Table78## Reference Repositories910- [TanStack Table](https://github.com/TanStack/table) - Headless table state and row models11- [Svelte](https://github.com/sveltejs/svelte) - Svelte 5 component and reactivity model1213## Upstream Grounding1415When TanStack Table adapter APIs, row models, controlled state, sorting, filtering, pagination, or Svelte rendering helpers affect correctness, ask DeepWiki a narrow question against `TanStack/table`. Verify against the installed `@tanstack/svelte-table` and `@tanstack/table-core` versions.1617This skill is for UI table state. Use `yjs` for Epicenter store table storage, and `svelte` for reading rows into a component.1819## Local API Baseline2021Epicenter currently uses `@tanstack/svelte-table` with:2223```typescript24import {25 createTable as createSvelteTable,26 FlexRender,27 renderComponent,28} from '@tanstack/svelte-table';29import type { ColumnDef } from '@tanstack/table-core';30```3132## Table Construction Rules3334- Always set `getRowId` for persisted or local-first rows. Do not rely on array index identity.35- Keep `data` referentially stable. Avoid creating a fresh array in the table options getter unless the table is intentionally rebuilt.36- Define columns with `satisfies ColumnDef<Row>[]`.37- Give accessor columns stable ids, especially when sorting, hiding, or persisted preferences are involved.38- Use `renderComponent` for reusable header and cell components.39- Include only row models the UI uses: core always, sorted/filter/pagination only when the surface needs them.4041## Controlled State4243- Control only state Epicenter owns externally, such as sorting, global filter, column visibility, row selection, or pagination.44- If an `onXChange` handler is present, the matching `state.get x()` must also be present.45- Keep state ownership in one component or handle. Do not split sorting, filters, and pagination across unrelated stores without a reason.4647## Rendering4849- TanStack Table owns row, column, and cell state. `@epicenter/ui/table` owns semantic table markup and styling.50- Render headers and cells with `FlexRender`.51- Key rows by `row.id` and cells by `cell.id`.52- Empty states stay in `ui-design`: when row count is zero, render `Empty.Root` in the table body or surrounding panel.53- Add explicit keyboard behavior for clickable rows. A click handler alone is not a row interaction model.54- Use TanStack Virtual separately for large lists. Do not treat virtualization as a built-in table feature.