Skip to content
Frontend
Skill

/data-table

Build virtualized data tables with @virtuoso.dev/data-table. Use this skill when (1) building a data grid with sorting, filtering, or grouped rows, (2) installing the shadcn-styled or headless table, (3) connecting remote/paginated data sources, (4) adding sticky, resizable,

BOOST
From plugin
react-virtuoso
6.5k4 skills
Install
$ npx -y skills add petyosi/react-virtuoso --skill data-table --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/data-table

Context preview

The summary Claude sees to decide when to auto-load this skill.

Build virtualized data tables with @virtuoso.dev/data-table. Use this skill when (1) building a data grid with sorting, filtering, or grouped rows, (2) installing the shadcn-styled or headless table, (3) connecting remote/paginated data sources, (4) adding sticky, resizable,

SKILL.md

data-table.SKILL.md
name: data-table
description: >-
  Build virtualized data tables with @virtuoso.dev/data-table. Use this skill when (1) building a data grid with sorting, filtering,
  or grouped rows, (2) installing the shadcn-styled or headless table, (3) connecting remote/paginated data sources, (4) adding sticky,
  resizable, reorderable, or hideable columns, (5) persisting table state, (6) controlling a table from outside (scrolling, actions),
  (7) migrating from TableVirtuoso, or any task involving VirtuosoDataTable, DataTable, DataTableColumn, localModel, remoteModel,
  or engine refs like scrollToRow$ and dispatchModelAction$.

@virtuoso.dev/data-table

A virtualized React data table (rows and columns) with grouped rows, sticky columns, column resizing/reordering/visibility, state persistence, and remote data support. It is the successor to `TableVirtuoso` for table-shaped problems: instead of row renderers, you pass a data source (model) and declare columns as JSX.

Installation: two paths

**Shadcn (pre-styled wrapper)** — for projects using shadcn/ui conventions:

npx shadcn@latest add petyosi/react-virtuoso/data-table

This installs a styled wrapper at `@/components/ui/data-table` exporting `DataTable`, `DataTableColumn`, `DataTableColumnHeader`, `DataTableCell`. Optional feature UI parts are separate registry items:

npx shadcn@latest add petyosi/react-virtuoso/data-table-resize-handle
npx shadcn@latest add petyosi/react-virtuoso/data-table-sort-header-button

The registry item names are hyphenated. The installed imports remain nested (`@/components/ui/data-table/column-resize`, `@/components/ui/data-table/column-sort`). Do not run path-shaped shadcn commands such as `data-table/column-resize` or `data-table/column-sort`; shadcn resolves registry item names, not import paths.

**Headless** — for custom design systems:

npm install @virtuoso.dev/data-table

Import the structural styles (`@import '@virtuoso.dev/data-table/styles.css'`) and use the unstyled `VirtuosoDataTable`, `Column`, `ColumnHeader`, `Cell`. Ask which path fits the project before installing; the shadcn wrapper is the faster start in Tailwind/shadcn codebases.

Minimal example (shadcn wrapper)

import { DataTable, DataTableCell, DataTableColumn, DataTableColumnHeader } from '@/components/ui/data-table'
import { localModel } from '@virtuoso.dev/data-table'

const model = localModel({ data: products })

export default function App() {
  return (
    <DataTable model={model} style={{ height: 360 }}>
      <DataTableColumn field="name">
        <DataTableColumnHeader>Product</DataTableColumnHeader>
        <DataTableCell className="font-medium">{({ cellValue }) => String(cellValue)}</DataTableCell>
      </DataTableColumn>
    </DataTable>
  )
}

Columns are JSX, not config objects. `field` is both the row-data lookup key and the column's public identifier (used by visibility, reordering, persistence). The table needs a real height, like every Virtuoso component.

Treat `field` and `id` as stable column identities, not as user-facing labels. Add an explicit `DataTableColumnHeader` for every visible column. This is especially important for display-only columns such as `actions`: use a visible label like `Actions` unless the product intentionally wants an icon-only/headerless column, in which case use `sr-only` text for accessibility.

When a table should fill the remaining height in a page, panel, or card, use a measured flex column instead of a fixed pixel height. Every flex ancestor between the measured container and the table needs `min-h-0`; non-table chrome should be `shrink-0`; the table should be the growing child with `style={{ height: '100%' }}`:

<section className="flex h-full min-h-0 flex-col">
  <PageHeader className="shrink-0" />
  <div className="flex min-h-0 flex-1 flex-col gap-3">
    <Toolbar className="shrink-0" />
    <DataTable className="min-h-0 flex-1" model={model} style={{ height: '100%' }}>
      {/* columns */}
    </DataTable>
  </div>
</section>

This is optional. If the parent does not have a definite height, keep using a fixed height (`style={{ height: 360 }}`) or choose `useWindowScroll` / `customScrollParent` deliberately.

Column widths are owned by the table through header measurements. Put base width classes such as `w-*`, `min-w-*`, and `basis-*` on `DataTableColumnHeader`, not on `DataTableCell`. Cells render inside tracks sized from header measurements; cell width utilities can force body content outside those tracks and make columns overlap at narrow widths. Use cell `className` for typography, alignment, padding, truncation, and color. For complex cell content, put `min-w-0` on an inner wrapper instead of widening the cell.

A growing header has separate measurement and presentation surfaces. The table measures the intrinsic header first, then adds spare width according to `grow`. If that same measured element stretches across the rendered column, ResizeObserver reports the grown width as the next base width and the column cannot shrink when its viewport narrows.

  • Use `DataTableColumnHeader.className` for the intrinsic surface: fixed or minimum base width, padding, typography, and alignment within that base width.
  • Use `DataTableColumnHeader.containerProps` for paint and interaction across the rendered column: background, hover/focus state, outline, box shadow, cursor, ARIA attributes, and event handlers.
  • Do not use width, flex, margin, padding, border, display, or `justify-*` styles in `containerProps`. The table owns the outer geometry; layout styles there can clip content and move `HeaderEnd` or `HeaderEdge` slots. Use `box-shadow` or `outline` for full-width separators.
  • Events on `containerProps` receive bubbled events from sort buttons, resize handles, reorder controls, and other nested UI. Stop propagation in the nested control or guard the container handler before running a whole-header action.
Read more
Ships withreact-virtuoso

The most complete React virtualization rendering family of components. Variable sized items out of the box; no manual measurements or hard-coding item heights is necessary; Chat message list UI; Grouped mode with sticky headers; Responsive grid layout;

Get the whole plugin
Stats
6,464
Stars
357
Forks
Active
Maintenance
TypeScript
Language
6d ago
Last commit
7y ago
Created
16h ago
Added

Repo: petyosi/react-virtuoso

Other skills on react-virtuoso.