Installation
Install the core grid from the @gridcn registry. No npm package.
The shadcn CLI distributes gridcn entirely from the hosted
@gridcn registry (gridcn.vercel.app), built from this
repository's GitHub registry. There is no npm
package: the source files are copied into your project.
Install the core grid
pnpm dlx shadcn@latest add @gridcn/data-grid
The CLI resolves the @gridcn registry from the hosted site
(gridcn.vercel.app). No namespace registration needed. To pin
a tag, branch, or commit, use the
GitHub registry path instead:
npx shadcn add DammersCode/gridcn/data-grid#v1.0.0.
The command installs the engine: range selection, keyboard, editing, built-in cell types, and spreadsheet clipboard. The Manual tab links every file and folder to its source in the repository, for an install without the CLI.
Add optional pieces
Each add-on is independently installable and depends only on the core. Check the ones you want and the command joins them in one call:
pnpm dlx shadcn@latest add @gridcn/data-grid-fill @gridcn/data-grid-presence @gridcn/data-grid-pinned-rows @gridcn/data-grid-history @gridcn/data-grid-toolbar @gridcn/data-grid-sort-list @gridcn/data-grid-context-menu @gridcn/data-grid-keybindings @gridcn/data-grid-io @gridcn/data-grid-url-state @gridcn/data-grid-lazy @gridcn/data-grid-pagination
See each feature's docs page for what it adds and its own install command.
Pinned installs
The hosted @gridcn registry always serves the current deploy of main. To pin a specific tag,
branch, or commit, use the GitHub registry path and append #<ref> after the item name:
pnpm dlx shadcn add DammersCode/gridcn/data-grid#v1.0.0
Without a ref, the CLI uses the repository's default branch.
The ref applies to the item you name only. The CLI resolves that item's registryDependencies
(for example DammersCode/gridcn/data-grid) without the ref. So a pinned add-on still installs
the core from the default branch. To pin the whole install, install the core first with the same
ref, then the add-on.
An @gridcn add-on install fetches the core through git ls-remote and
raw.githubusercontent.com. It needs git on the PATH and access to GitHub.
Alternative: GitHub registry (no setup)
The same items are available directly from this repository's GitHub registry: no namespace registration, and the only path that supports ref pinning:
pnpm dlx shadcn add DammersCode/gridcn/data-grid
Both paths install the same files from the same source.
Prerequisites
Your project needs shadcn/ui already initialized (npx shadcn init), Tailwind v4, and React 19.
See shadcn's own installation guide if you have not
run npx shadcn init yet. This command creates components.json at the root of your project.
gridcn's CLI commands read that file to find your aliases and styling. See
Project status & compatibility for why React 19 is a
hard floor, plus the Node and TypeScript floors.
React 19 and Tailwind v4 only
On React 18, the grid does not run: it reads context through the React 19 use() API. On
Tailwind v3, the grid renders without its styles.
The table below lists, for every item, the npm packages it installs and the shadcn/ui components
the CLI adds with it. The core is the only item with a hard tooltip component dependency.
| Item | Runtime dependency | Dev dependency | shadcn components added |
|---|---|---|---|
Core (data-grid) | zustand, use-sync-external-store, lucide-react, @base-ui/react | none | button, input, select, checkbox, popover, calendar, dropdown-menu, context-menu, separator, tooltip |
data-grid-toolbar | @dnd-kit/dom, @dnd-kit/react, lucide-react | none | dropdown-menu, popover, input, button, badge, select |
data-grid-sort-list | @dnd-kit/dom, @dnd-kit/react, lucide-react | none | popover, button, badge, select |
data-grid-context-menu | lucide-react, @base-ui/react, zustand | none | context-menu, dropdown-menu, tooltip |
data-grid-keybindings | none beyond the core | none | dialog |
data-grid-pagination | lucide-react | none | button, select |
data-grid-io | hucre@1.1.0 (lazy-loaded), papaparse (loaded with the item), lucide-react | @types/papaparse | dialog, select, dropdown-menu, button (plus dropzone) |
data-grid-find-replace | lucide-react | none | button, input |
data-grid-url-state | nuqs | none | none (installs data-grid-pagination) |
data-grid-presence, data-grid-fill, data-grid-pinned-rows | zustand | none | none |
dropzone | lucide-react | none | none |
data-grid-history, data-grid-lazy, data-grid-status-bar | none beyond the core | none | none |
The registry pins hucre to an exact version. hucre limits the unpacked size and the cell
count of an untrusted spreadsheet before it allocates the cells.
Tooltips
The CLI prints a hint to wrap your app in TooltipProvider. The grid works without it. The core
uses a tooltip for the message of an invalid cell, and the context menu uses one for a disabled
item. A tooltip without a provider opens after the default hover delay. A provider sets one
shared delay for all tooltips of the app. The tooltip component of shadcn/ui sets that delay
to zero. Wrap your app once in the root layout if you want instant tooltips:
import { TooltipProvider } from "@/components/ui/tooltip";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<TooltipProvider>{children}</TooltipProvider>
</body>
</html>
);
}Where files land
registry:component and registry:block files install under the aliases.components path in
your components.json (@/components by default). So the data-grid item lands at
components/data-grid/*, with a single public barrel at
components/data-grid/data-grid.tsx. Import from that barrel, not from individual files.
import { DataGrid, defineColumns } from "@/components/data-grid/data-grid";Add-ons follow the same pattern (components/data-grid-history/data-grid-history.ts, etc.). The
data-grid install also writes components/data-grid/LICENSE.md: the text of the Apache
License 2.0, which applies to the installed files.
Framework notes
Next.js
gridcn works by default in the App Router. Every grid component is a client component, with
"use client" at the top of each file, so no extra configuration is necessary.
Vite
gridcn works the same way in Vite. The CLI detects your Vite and shadcn setup from
components.json, and it writes files to the aliases in that file. The @ alias in
vite.config.ts must point to the same folder, as in shadcn's Vite setup:
import path from "node:path";
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: { "@": path.resolve(__dirname, "./src") },
},
});Add the same alias to compilerOptions.paths in tsconfig.app.json, so TypeScript resolves
@/components/... imports too.
Non-default aliases
Your components.json can use non-default aliases. An example is components pointed at
src/components instead of @/components, or no @/* path prefix at all. If so, the shadcn
CLI rewrites the internal @/registry/...-style imports of gridcn to your aliases automatically
on install.
Known problem: missing alias
If an install leaves an import unresolved, make sure that:
aliases.components,aliases.ui,aliases.lib, andaliases.hooksare all set incomponents.json. When an alias is missing, some CLI versions leave the import unresolved, and other CLI versions rewrite it to a wrong path. The exact result depends on the CLI version.- Your
tsconfig.jsonorvite.config.tspath mapping matches those aliases. The CLI writes files assuming that the mapping exists. It does not create the mapping for you.
If imports are still wrong after install, fix the handful of import lines by hand instead of fighting the alias resolver. The files belong to you.
// Before (unresolved after install, missing aliases.hooks)
import { useDataGridActions } from "hooks/use-data-grid-actions";
// After (matches your tsconfig.json / vite.config.ts path mapping)
import { useDataGridActions } from "@/hooks/use-data-grid-actions";Verify
Add the columns and data shape of the hero demo from the quick start to any
page. Click a cell, type a value, and press Enter to make sure that editing works. If the grid
displays without styles, make sure that your global.css imports Tailwind and that shadcn's base
tokens are present. gridcn uses only existing shadcn tokens, with no new CSS variables beyond
--grid-row-height and --grid-pin-shadow (the edge shadow color). The CLI adds
--grid-pin-shadow to your CSS for light and dark mode. See
Styling & theming.