Tabular
@sectile/tabular is renderer-neutral core for query, selection, cursor, editing, and hierarchy state. Choose DataTable, DataGrid, or DataTreeGrid according to the interaction density of the surface.
pnpm add @sectile/tabularChoose a profile first
| Question | Choose |
|---|---|
| Do users read, compare, sort, filter, and select rows? | DataTable |
| Must every cell support arrow navigation and editing? | DataGrid |
| Does the grid also need parent and child branches? | DataTreeGrid |
Start from one data contract
Keep shared capabilities intact, then choose the interaction profile that matches how the surface is navigated.
- Identity
- row · column · cell · group ID
- Schema
- columns · nested headers · capabilities
- Query
- sort · filter · group · aggregate · pivot
- Source
- request · source · view revision
- Access
- page · window · visible counts
- Selection
- explicit row · all-matching
- Columns
- order · hidden · pinned start/end
- Ownership and safety
- controlled slices · limits · atomic errors
DataTable
Read and compare rows
- Native table and form semantics
- Sort, filter, and row selection
- Group-row disclosure
- Edit commit intent
DataTable
Native table semantics, query controls, checkbox selection, and form integration.
Search, sorting, and selection share one projection.<script setup lang="ts">
import {
createDataTableComponents,
useDataTable,
} from '@sectile/vue/data-table'
const table = useDataTable({
source: resolveUsers,
})
const DataTable = createDataTableComponents(table)
</script>
<template>
<DataTable.Provider>
<DataTable.Root>
<DataTable.Caption>사용자</DataTable.Caption>
<DataTable.Header><DataTable.HeaderRow>
<DataTable.ColumnHeader column="name">
<DataTable.SortTrigger column="name">이름</DataTable.SortTrigger>
</DataTable.ColumnHeader>
<DataTable.ColumnHeader column="team">팀</DataTable.ColumnHeader>
<DataTable.ColumnHeader column="status">상태</DataTable.ColumnHeader>
</DataTable.HeaderRow></DataTable.Header>
<DataTable.Body v-slot="{ row }">
<DataTable.Cell column="name">{{ row.cells.name }}</DataTable.Cell>
<DataTable.Cell column="team">{{ row.cells.team }}</DataTable.Cell>
<DataTable.Cell column="status">{{ row.cells.status }}</DataTable.Cell>
</DataTable.Body>
</DataTable.Root>
</DataTable.Provider>
</template>Explore every DataTable feature →
DataGrid
Two-dimensional cursor, roving focus, edit/commit/cancel, and cursor recovery.
{"cursor":null,"selected":{"kind":"explicit-rows","rowIDs":[]}}<script setup lang="ts">
import { createDataGridComponents, useDataGrid } from '@sectile/vue/data-grid'
const grid = useDataGrid({ source: resolveWork })
const DataGrid = createDataGridComponents(grid)
</script>
<template><DataGrid.Provider><DataGrid.Root aria-label="출시 준비">
<DataGrid.Header><DataGrid.HeaderRow><DataGrid.ColumnHeader column="task">작업</DataGrid.ColumnHeader><DataGrid.ColumnHeader column="owner">담당자</DataGrid.ColumnHeader><DataGrid.ColumnHeader column="status">상태</DataGrid.ColumnHeader></DataGrid.HeaderRow></DataGrid.Header>
<DataGrid.Body v-slot="{ row }"><DataGrid.Cell column="task">{{ row.cells.task }}</DataGrid.Cell><DataGrid.Cell column="owner">{{ row.cells.owner }}</DataGrid.Cell><DataGrid.Cell column="status">{{ row.cells.status }}</DataGrid.Cell></DataGrid.Body>
</DataGrid.Root></DataGrid.Provider></template>Explore every DataGrid feature →
DataTreeGrid
DataGrid plus expansion, hierarchy metadata, and retained parent context.
{"cursor":null,"edit":"navigation","visibleRows":0}<script setup lang="ts">
import { createDataTreeGridComponents, useDataTreeGrid } from '@sectile/vue/data-tree-grid'
const tree = useDataTreeGrid({ source: resolveServices })
const DataTreeGrid = createDataTreeGridComponents(tree)
</script>
<template><DataTreeGrid.Provider><DataTreeGrid.Root aria-label="서비스 소유권">
<DataTreeGrid.Header><DataTreeGrid.HeaderRow><DataTreeGrid.ColumnHeader column="service">서비스</DataTreeGrid.ColumnHeader><DataTreeGrid.ColumnHeader column="owner">담당자</DataTreeGrid.ColumnHeader><DataTreeGrid.ColumnHeader column="status">상태</DataTreeGrid.ColumnHeader></DataTreeGrid.HeaderRow></DataTreeGrid.Header>
<DataTreeGrid.Body v-slot="{ row }"><DataTreeGrid.Cell column="service"><DataTreeGrid.RowDisclosure v-if="row.kind === 'group'" />{{ row.cells.service }}</DataTreeGrid.Cell><DataTreeGrid.Cell column="owner">{{ row.cells.owner }}</DataTreeGrid.Cell><DataTreeGrid.Cell column="status">{{ row.cells.status }}</DataTreeGrid.Cell></DataTreeGrid.Body>
</DataTreeGrid.Root></DataTreeGrid.Provider></template>Explore every DataTreeGrid feature →
Choose a layer
| Needed scope | Install | Import |
|---|---|---|
| State, query, and projection | @sectile/tabular | @sectile/tabular/data-* |
| Existing HTML elements | @sectile/dom @sectile/tabular | @sectile/dom/tabular |
| Vue compound components | @sectile/vue @sectile/tabular vue | @sectile/vue/data-table, @sectile/vue/data-grid, @sectile/vue/data-tree-grid |
@sectile/tabular knows nothing about DOM, Vue, or terminals. It is an optional peer of @sectile/dom and @sectile/vue, so install it only when using their Tabular subpaths. Tabular has no terminal host.
Every example's Code tab presents the same feature in Vue, DOM, and Core. Verify the interaction first, then choose the implementation for your environment.
Continue by task
| Task | Guide |
|---|---|
| Understand IDs, query, selection, and revisions | Shared contracts |
| Server sorting, filtering, paging, loading, and retry | Async sources |
| Connect existing elements and events | DOM composition |
| Typed components, Provider, slots, and SSR | Vue composition |
| Window only genuinely large views | Virtualization |
Responsibility boundary
Tabular produces deterministic next state, projections, and commands from events. The application owns network, cache, persistence, and loading/empty/error presentation. DOM or Vue hosts own elements, focus, forms, measurement, and scroll. Shared contracts and async sources demonstrate these boundaries.
Public subpaths
| Path | Responsibility |
|---|---|
/model | IDs, immutable model, controlled ownership, limits |
/query | Filter, sort, group, aggregate, and pivot descriptors |
/source | Request/response, page/window, client source |
/data-table | Read-oriented table controller |
/data-grid | Cell-oriented grid controller |
/data-tree-grid | Hierarchical grid controller |
/virtual | Optional adapter for consumer-installed @sectile/virtual |
