Capítulo 31 de 54
columnPinningFeature splits columns into logical start/center/end regions (start≈left, end≈right in LTR — swapped in RTL), which you render either as one table using sticky CSS positioning, or as genuinely separate tables per region using the region-scoped getters.
columnPinning: { start: string[], end: string[] } — everything not listed is implicitly "center" (unpinned). Pin defaults via initialState.columnPinning: { start: [...], end: [...] }.columnOrder → grouping) — columnOrder only reorders within the center region; the only way to reorder within a pinned side is editing columnPinning.start/.end directly.atoms: { columnPinning: atom } (v9-recommended) or classic state.columnPinning + onColumnPinningChange — same tradeoffs as any other state slice.column.getCanPin(), column.pin('start' | 'end' | false) (pin/unpin), column.getIsPinned() (which side, or false), column.getPinnedIndex() (position within its pinned group), column.getStart()/column.getAfter() (the correct left/right-equivalent CSS offset for sticky positioning), column.getIsFirstColumn()/getIsLastColumn() (edge-of-group check, useful for a boundary box-shadow).table.setColumnPinning({...}), table.resetColumnPinning() (→ initialState), table.resetColumnPinning(true) (→ both arrays empty); table.getIsSomeColumnsPinned() (optionally scoped to 'start'/'end').getStartLeafColumns/getCenterLeafColumns/getEndLeafColumns, plus *VisibleLeafColumns variants), header/footer groups (getStartHeaderGroups/getCenterHeaderGroups/getEndHeaderGroups, get*FooterGroups), flat/leaf headers per region, and row-level row.getStartVisibleCells()/getCenterVisibleCells()/getEndVisibleCells(). table.getPinnedLeafColumns(position) / getPinnedVisibleLeafColumns(position) take the region as a parameter instead.table.getHeaderGroups()/row.getVisibleCells(), use column.getIsPinned()/getStart()/getAfter() to apply position: sticky and offsets; (2) split tables — render 2-3 separate <table>s using the region-scoped getters, one per pinned side plus center, when you want fully independent scroll/layout per region.const features = tableFeatures({ columnPinningFeature })
const table = useTable({
features, columns, data,
initialState: { columnPinning: { start: ['expand'], end: ['actions'] } },
})
// sticky-CSS single-table approach
const style = column.getIsPinned() === 'start'
? { position: 'sticky', left: column.getStart(), zIndex: 1 }
: column.getIsPinned() === 'end'
? { position: 'sticky', right: column.getAfter(), zIndex: 1 }
: undefined
getIsPinned() plus getStart()/getAfter() is enough to position any pinned column correctly relative to its neighbors.columnPinning.start/.end directly — setColumnOrder doesn't reach pinned columns.start/end are logical, not literal left/right — they flip automatically under RTL, so don't hardcode left/right styling logic based on the pin side name alone.