# @toolbox-web/grid — Full Documentation
> A high-performance, framework-agnostic data grid built with pure TypeScript and native Web Components. Zero runtime dependencies.
This file concatenates every prose documentation page — guides, plugins, and
framework adapters — into one document for one-shot ingestion. Demo code is
inlined as fenced blocks. To keep the file ingestion-friendly, plugin pages are
condensed to a stub — intro, `Installation`, and `Basic Usage` — with each
plugin's deep API (configuration options, events, methods) linked as a `.md`
companion; fetch it by appending `.md` to the plugin's page URL. The exhaustive
per-symbol TypeDoc API is likewise linked (not inlined) at the end. For the
curated link index, see `llms.txt`.
A few non-implementation pages (the changelogs and the AI-assistance overview) are
intentionally omitted here to keep the corpus focused on building with the grid; they
remain linked in `llms.txt`.
---
## Contents
Every entry below appears in full further down this file under an `#
` heading — grep for that exact heading to jump to it, or fetch the single-page `.md` URL instead of the whole corpus. Plugin pages appear here as a stub (intro + install + basic usage); their deep API lives at the linked `.md`.
### Core Documentation
- **Introduction** — A high-performance, framework-agnostic data grid web component for JavaScript, React, Angular, and Vue. Zero dependencies, 100k+ rows, virtualized rendering. (https://toolboxjs.com/grid/introduction.md)
- **Getting Started** — Install @toolbox-web/grid and render your first grid in under a minute. Covers npm, CDN, ES modules, declarative HTML, and full framework integration for Vanilla JS, React, Vue, and Angular. (https://toolboxjs.com/grid/getting-started.md)
- **Core Features** — Interactive playground, configuration, rendering, loading states, variable row heights, events, methods, and more for @toolbox-web/grid. (https://toolboxjs.com/grid/core.md)
- **Architecture** — Internal architecture of @toolbox-web/grid — configuration system, render scheduler, virtualization, plugin lifecycle, and light DOM design. (https://toolboxjs.com/grid/architecture.md)
- **API Reference** — Complete reference for the component — properties, methods, events, CSS custom properties, keyboard shortcuts, declarative configuration, and accessibility. (https://toolboxjs.com/grid/api-reference.md)
- **Error & Warning Reference** — Complete reference for all diagnostic codes emitted by @toolbox-web/grid. Each code links to an explanation and resolution steps. (https://toolboxjs.com/grid/errors.md)
- **Platform & Support** — What you can rely on when you depend on @toolbox-web/grid — adapter support matrix, browser baseline, CSP & security handling, server-side rendering, deprecation policy, and release cadence. (https://toolboxjs.com/grid/platform.md)
- **Plugins Overview** — Overview of all @toolbox-web/grid plugins — editing, selection, filtering, grouping, export, and more. Tree-shakeable, individually importable. (https://toolboxjs.com/grid/plugins.md)
### Guides
- **Accessibility** — How @toolbox-web/grid implements WAI-ARIA grid patterns, keyboard navigation, screen reader support, and high contrast mode. (https://toolboxjs.com/grid/guides/accessibility.md)
- **Automated testing** — Write reliable Playwright, Cypress, and WebdriverIO tests against @toolbox-web/grid using its stable CSS classes, data attributes, ARIA roles, and ready() / 'render' event lifecycle hooks. (https://toolboxjs.com/grid/guides/automated-testing.md)
- **Internationalization** — Translating @toolbox-web/grid — screen reader announcements, plugin UI strings, cell value formatting, and right-to-left layout. (https://toolboxjs.com/grid/guides/i18n.md)
- **Performance** — Optimize @toolbox-web/grid for large datasets — virtualization tuning, bundle optimization, rendering best practices, and benchmarks. (https://toolboxjs.com/grid/guides/performance.md)
- **Theming** — Customize @toolbox-web/grid with CSS custom properties — colors, spacing, typography, dark mode, pre-built themes, and cascade layers. (https://toolboxjs.com/grid/guides/theming.md)
- **Touch Input** — How @toolbox-web/grid works on touch devices — gesture map, long-press interactions, hit-target sizing, and known browser quirks. (https://toolboxjs.com/grid/guides/touch-input.md)
- **Troubleshooting** — Solutions to common issues when working with @toolbox-web/grid — height and virtualization problems, performance tuning, plugin conflicts, and framework adapter development. (https://toolboxjs.com/grid/guides/troubleshooting.md)
### Plugins
- **Clipboard Plugin** — Copy and paste grid data with Excel-compatible clipboard support. (https://toolboxjs.com/grid/plugins/clipboard.md)
- **Column Virtualization Plugin** — Improve performance for grids with many columns by only rendering visible columns. (https://toolboxjs.com/grid/plugins/column-virtualization.md)
- **Context Menu Plugin** — Add right-click context menus to the grid with customizable items. (https://toolboxjs.com/grid/plugins/context-menu.md)
- **Editing Plugin** — Enable inline cell editing with built-in and custom editors. (https://toolboxjs.com/grid/plugins/editing.md)
- **Export Plugin** — Export grid data to CSV or other formats. (https://toolboxjs.com/grid/plugins/export.md)
- **Filtering Plugin** — Add column-level filtering with built-in filter panel and custom filters. (https://toolboxjs.com/grid/plugins/filtering.md)
- **Column Grouping Plugin** — Group columns visually under shared parent headers. (https://toolboxjs.com/grid/plugins/grouping-columns.md)
- **Row Grouping Plugin** — Group rows by column values with expandable groups. (https://toolboxjs.com/grid/plugins/grouping-rows.md)
- **Master-Detail Plugin** — Show expandable detail rows beneath data rows. (https://toolboxjs.com/grid/plugins/master-detail.md)
- **Multi-Sort Plugin** — Sort by multiple columns with shift-click support. (https://toolboxjs.com/grid/plugins/multi-sort.md)
- **Pinned Columns Plugin** — Pin columns to the left or right side of the grid. (https://toolboxjs.com/grid/plugins/pinned-columns.md)
- **Pinned Rows (Status Bar) Plugin** — Pin summary or custom rows to the top or bottom of the grid. (https://toolboxjs.com/grid/plugins/pinned-rows.md)
- **Pivot Table Plugin** — Transform row data into a cross-tabulation (pivot table) layout. (https://toolboxjs.com/grid/plugins/pivot.md)
- **Print Plugin** — Print the grid contents with configurable page settings. (https://toolboxjs.com/grid/plugins/print.md)
- **Column Reorder Plugin** — Allow users to reorder columns by drag and drop. (https://toolboxjs.com/grid/plugins/reorder-columns.md)
- **Responsive Plugin** — Automatically adapt the grid layout for different screen sizes. (https://toolboxjs.com/grid/plugins/responsive.md)
- **Row Drag-Drop Plugin** — Drag rows within a single grid (reorder) and across grids that share a drop zone. (https://toolboxjs.com/grid/plugins/row-drag-drop.md)
- **Selection Plugin** — Cell, row, and range selection with full keyboard support, conditional selection, and checkbox mode. (https://toolboxjs.com/grid/plugins/selection.md)
- **Server-Side Plugin** — Connect the grid to server-side data sources with virtual scrolling. (https://toolboxjs.com/grid/plugins/server-side.md)
- **Shell Plugin** — Wrap the grid with a header bar (title + toolbar) and a collapsible tool-panel sidebar. (https://toolboxjs.com/grid/plugins/shell.md)
- **Sticky Rows Plugin** — Pin selected data rows below the header as the user scrolls past them. (https://toolboxjs.com/grid/plugins/sticky-rows.md)
- **Tooltip Plugin** — Display popover tooltips for truncated header and cell text, with per-column overrides. (https://toolboxjs.com/grid/plugins/tooltip.md)
- **Tree Plugin** — Display hierarchical data as an expandable tree. (https://toolboxjs.com/grid/plugins/tree.md)
- **Undo/Redo Plugin** — Add undo/redo support for cell edits. (https://toolboxjs.com/grid/plugins/undo-redo.md)
- **Column Visibility Plugin** — Allow users to toggle column visibility via a panel. (https://toolboxjs.com/grid/plugins/visibility.md)
### Recipes
- **Recipes** — Task-oriented how-to guides for @toolbox-web/grid — editable grids, streaming data, scroll-driven UI, PDF export, spreadsheet formulas, in-cell charts, and input masking. (https://toolboxjs.com/grid/recipes.md)
- **Editable grid with undo** — Inline cell editing with undo/redo, dirty tracking, and validation that rejects a bad value before it is committed. (https://toolboxjs.com/grid/recipes/editable-grid-with-undo.md)
- **Real-time streaming data** — Push live WebSocket, SSE, or polling updates into the grid with row transactions, without re-assigning the whole dataset. (https://toolboxjs.com/grid/recipes/real-time-streaming.md)
- **Scroll & render driven UI** — Infinite scroll, lazy cell hydration, and focusing a freshly added row using the grid's tbw-scroll and render events. (https://toolboxjs.com/grid/recipes/scroll-and-render.md)
### Plugin Development
- **Plugin Development** — Build plugins that extend @toolbox-web/grid — lifecycle hooks, manifests, communication, feature registration, and bundling. (https://toolboxjs.com/grid/plugin-development.md)
- **Plugin Architecture** — How the @toolbox-web/grid plugin system works internally — lifecycle, hooks, communication, manifests, validated properties, and the feature registry. (https://toolboxjs.com/grid/plugin-development/architecture.md)
- **Custom Plugins** — Build custom plugins for @toolbox-web/grid — lifecycle hooks, communication, queries, manifests, testing, and complete examples. (https://toolboxjs.com/grid/plugin-development/custom-plugins.md)
### Framework Adapters
- **Framework Adapters** — How React, Angular, and Vue adapters let @toolbox-web/grid render framework-native components as cells, editors, and tool panels. (https://toolboxjs.com/grid/framework-adapters.md)
- **Framework Adapter Architecture** — How the @toolbox-web/grid framework-adapter system intercepts grid rendering to mount React, Angular, and Vue components in cells, editors, and tool panels. (https://toolboxjs.com/grid/framework-adapters/architecture.md)
### Angular
- **Base Classes for Editors & Filter Panels** — BaseGridEditor, BaseGridEditorCVA, BaseOverlayEditor, and BaseFilterPanel — reusable base classes for custom Angular editors and filter panels. (https://toolboxjs.com/grid/angular/base-classes.md)
- **Angular Integration** — Install and configure @toolbox-web/grid-angular — feature inputs, renderers, editors, events, inject functions, and Angular-specific patterns. (https://toolboxjs.com/grid/angular/getting-started.md)
- **Reactive Forms Integration** — Bind @toolbox-web/grid to Angular FormArray — cell-level validation, dirty tracking, lazy form binding, and automatic validation styling. (https://toolboxjs.com/grid/angular/reactive-forms.md)
### React
- **React Integration** — Install and configure @toolbox-web/grid-react — feature props, JSX renderers, editors, hooks, and event handling. (https://toolboxjs.com/grid/react/getting-started.md)
### Vue
- **Vue Components** — Props, slots, emits and exposed members for every component exported by @toolbox-web/grid-vue. (https://toolboxjs.com/grid/vue/components.md)
- **Vue Integration** — Install and configure @toolbox-web/grid-vue — feature props, slot renderers, editors, composables, and event handling. (https://toolboxjs.com/grid/vue/getting-started.md)
---
# Introduction
> A high-performance, framework-agnostic data grid web component for JavaScript, React, Angular, and Vue. Zero dependencies, 100k+ rows, virtualized rendering.
## CORPUS RETRIEVAL STRATEGY
Five corpus variants are published. **Pick the one that covers your stack:**
| File | Use when |
|------|----------|
| `llms-full-angular.txt` | Working in an Angular project |
| `llms-full-react.txt` | Working in a React project |
| `llms-full-vue.txt` | Working in a Vue project |
| `llms-full-vanilla.txt` | Plain TypeScript / JavaScript, no framework |
| `llms-full.txt` | Framework unknown, or multiple frameworks in one session |
Two smaller companions sit alongside them: `llms.txt` (curated link map of every prose page — read this first when you only need to find the right page) and `llms-api.txt` (every generated TypeDoc symbol linked to its `.md` companion — read this when you need an exact type signature).
These files are large (the per-framework variants are the smallest — they drop the
other stacks' examples and link runnable demos instead of inlining them; the
cross-framework `llms-full.txt` is the largest). If your tool cannot fetch or fully
process the file in one pass:
1. Download the right variant once: `curl -L https://toolboxjs.com/llms-full-angular.txt -o llms-full-angular.txt`
2. Search for the topic: `rg -n 'your keyword' llms-full-angular.txt`
3. Extract the matching region: `sed -n '1200,1320p' llms-full-angular.txt`
4. Paste only those slices into context — not the whole file.
**Keep the local copy fresh.** These files are regenerated on every docs build. A cached copy older than one week may reference stale API, wrong import paths, or removed features. Re-download before starting any significant implementation work.
Preferred retrieval order (smallest to largest): per-page `.md` companion (e.g. `/grid/plugins/editing.md`) → `llms.txt` index → framework-scoped `llms-full-{framework}.txt` local-grepped slices → `llms-full.txt` local-grepped slices.
Because this introduction always sorts first in the corpus, you are reading these instructions even if your context window is smaller than the full file.
## WHERE TO LOOK — task → page
Route the user's request to the page that answers it, then fetch that page's `.md`
companion (or grep for its `# ` heading inside a corpus file). Prefer ONE
targeted page over re-reading the whole corpus. Every path below is relative to
`https://toolboxjs.com` (e.g. `https://toolboxjs.com/grid/getting-started.md`).
| The user wants to… | Read |
|---|---|
| Install and render a first grid | `/grid/getting-started.md` |
| Define columns, formatting, sorting, sizing, row height | `/grid/core.md` |
| See every config option / type signature | `/grid/api-reference.md`, then `llms-api.txt` |
| Know which plugin solves a need, and compatibility | `/grid/plugins.md` |
| Load data from a server, paginate, infinite-scroll | `/grid/plugins/server-side.md` |
| Edit cells, validate input, custom editors | `/grid/plugins/editing.md` |
| Filter, search, or build a filter panel | `/grid/plugins/filtering.md` |
| Select rows/cells/ranges, copy to clipboard | `/grid/plugins/selection.md`, `/grid/plugins/clipboard.md` |
| Group, aggregate, pivot, or show a tree | `/grid/plugins/grouping-rows.md`, `/grid/plugins/pivot.md`, `/grid/plugins/tree.md` |
| Export to CSV/Excel, or print | `/grid/plugins/export.md`, `/grid/plugins/print.md` |
| Restyle, theme, or use dark mode | `/grid/guides/theming.md` |
| Fix a blank / zero-height / non-rendering grid | `/grid/guides/troubleshooting.md` |
| Understand a `TBW###` console warning or error | `/grid/errors.md` |
| Make it fast with large datasets | `/grid/guides/performance.md` |
| Wire it up in React / Vue / Angular | `/grid/react/getting-started.md`, `/grid/vue/getting-started.md`, `/grid/angular/getting-started.md` |
| Handle SSR, CSP, or browser support | `/grid/platform.md` |
| Check supported framework versions, deprecation policy, or release cadence | `/grid/platform.md` |
| Translate the grid, or lay it out right-to-left | `/grid/guides/i18n.md` |
| Write tests against the grid | `/grid/guides/automated-testing.md` |
| Meet accessibility requirements | `/grid/guides/accessibility.md` |
| Solve a recurring real-world pattern | `/grid/recipes.md` |
| Build a custom plugin or extend the grid | `/grid/plugin-development/custom-plugins.md` |
| Upgrade from v2 | `/grid/guides/migration-v3.md` |
## RULE 0 (HIGHEST PRIORITY) — Prefer a single `gridConfig` over fragmented props
When generating grid code for ANY framework (React, Angular, Vue, vanilla JS/TS, Svelte), **default to one `gridConfig` object** holding columns, `features`, and other configuration. Reserve framework props for reactive data (`rows`) and the imperative `ref`/handle. Do NOT spread configuration across many individual props/inputs/attributes unless the user explicitly asks.
WHY: one object describes the whole grid, is portable across frameworks (the same `GridConfig` works in vanilla, React, Angular, Vue), and keeps multi-line config (callbacks like `groupOn`, `dataSource`, renderers) readable.
```ts
const gridConfig: GridConfig = {
columns: [/* … */],
features: { selection: 'range', editing: 'dblclick' },
};
```
- **React:** `` (memoize with `useMemo`)
- **Angular:** ``
- **Vue:** `` (wrap with `markRaw()`)
- **Vanilla:** `const grid = createGrid(gridConfig); grid.rows = data;`
Individual feature props (``) remain fully supported — use them ONLY for very small grids (≤ 2 features, each a boolean/short string) or when explicitly requested.
## RULE 0.1 — Framework adapters must use framework-native renderers/editors
When the user is inside **React/Vue/Angular**, treat framework-native renderer/editor APIs as default best practice:
- **React:** JSX/component renderers/editors
- **Vue:** slot/component renderers/editors
- **Angular:** `*tbwRenderer`, template/component renderers/editors
Do **not** default to plain `HTMLElement` renderer/editor functions in adapter code unless the user explicitly asks for framework-agnostic/vanilla output.
## RULE 0.2 — Prefer features, not manual plugin instances
Default to `gridConfig.features` + side-effect feature imports. Treat manual plugin instantiation (`plugins: [new SelectionPlugin()]`) as an advanced exception, primarily for custom plugin development or narrowly-scoped imperative cases.
If imperative access is needed after initialization, prefer `grid.getPluginByName('...')` over storing manually-created plugin instances in application code.
## RULE 0.3 — Import from the framework adapter, co-located, framework-scoped
Inside a **React / Vue / Angular** project, get import hygiene right — these are the mistakes agents make most:
1. **Import runtime values from the adapter package, never from core.** The component, hooks/composables, providers, directives, and any plugin classes come from `@toolbox-web/grid-{react,vue,angular}`. Do NOT import runtime values (components, `createGrid`, plugin classes) from `@toolbox-web/grid` in framework code.
2. **Import `GridConfig` / `ColumnConfig` from the adapter — NEVER from core.** All three adapters (`@toolbox-web/grid-react`, `@toolbox-web/grid-vue`, `@toolbox-web/grid-angular`) re-export their OWN `GridConfig` / `ColumnConfig` (plus `CellRenderer` / `CellEditor`) that widen `renderer` / `editor` to accept framework components — JSX nodes (React), slots/components (Vue), or component classes (Angular: `{ field: 'x', renderer: MyComponent }`). The base types in `@toolbox-web/grid` type `renderer` as returning `HTMLElement | string` only, so importing them in framework code makes your component renderer/editor fail to type-check. So: `import type { GridConfig, ColumnConfig } from '@toolbox-web/grid-react';` (or `-vue` / `-angular`). Only reach into `@toolbox-web/grid` for types the adapter does not re-export (event-detail types like `CellCommitDetail`, enums, plugin option interfaces).
3. **Never add a bare `import '@toolbox-web/grid';`.** It is redundant in React/Vue/Angular — importing the adapter (`@toolbox-web/grid-{react,vue,angular}`) or any of its `features/*` entries already registers the `` custom element as a side effect. A standalone grid-core import is only for vanilla JS/TS with no adapter.
4. **Use the adapter's feature path, not core's.** Inside a framework, side-effect imports must be `@toolbox-web/grid-react/features/selection` (the adapter path), NOT `@toolbox-web/grid/features/selection`. The adapter entry installs the framework-native renderer/editor bridges on top of the core feature — the core path alone can silently drop framework support.
5. **Co-locate feature imports with the grid.** Put `import '@toolbox-web/grid-react/features/…';` in the **same module that renders the grid**, right next to the component that uses it — NOT globally in `main.ts` / `main.tsx` / `App.tsx` / `app.config.ts`. Setup belongs beside its use; a global side-effect import hides which grid needs the feature and defeats per-route code-splitting.
WHY: mixing `@toolbox-web/grid` and `@toolbox-web/grid-react` imports (especially the config types), or registering features globally, produces grids that build but silently miss framework-native rendering — or fail to type-check the moment you pass a component as a `renderer` — and makes the dependency graph impossible to reason about.
## CRITICAL RULES — read before generating any code
These apply to ALL frameworks. Violating them produces broken grids.
1. **Side-effect imports are always required.** `gridConfig.features.X` (or a feature prop) does NOT remove the need to import the feature factory — without the import the merge produces no plugin:
```ts
import '@toolbox-web/grid/features/selection'; // vanilla JS/TS only (no adapter)
import '@toolbox-web/grid-react/features/selection'; // inside a framework — use the adapter path (see RULE 0.3)
```
Put this import in the same module that renders the grid, not in a global entry file. Vanilla JS must also register the element itself: `import '@toolbox-web/grid';` (adapters auto-import it, so never add it in framework code).
2. **Height is required.** The grid needs an explicit height or it renders at zero height: `tbw-grid { height: 400px; }`. (`display: block` is set automatically — do not add it.)
3. **Editing is opt-in.** `editable: true` on a column WITHOUT the editing feature/plugin throws. Load `@toolbox-web/grid/features/editing` and set `features: { editing: true }`.
4. **Plugin load order matters when using plugin API directly.** `ClipboardPlugin` requires `SelectionPlugin`; `UndoRedoPlugin` requires `EditingPlugin` — load the dependency first. Prefer `features` so ordering/dependencies are handled automatically.
5. **Some plugins are mutually exclusive.** `GroupingRows` ✗ `Tree` ✗ `Pivot` (all rewrite the row model); `ServerSide` ✗ `Pivot`. A dev-mode warning fires on conflict. (`ServerSide` + `Tree` and `ServerSide` + `GroupingRows` DO coexist.)
6. **Light DOM, no Shadow DOM.** CSS cascade works normally — no `::part()`/`::slotted()`.
7. **Em-based sizing.** All dimensions use `em`; scale the whole grid by changing `font-size` on `tbw-grid`.
8. **Type import:** `import type { DataGridElement } from '@toolbox-web/grid';` (`GridElement` is a legacy alias of the same type).
## ANTI-PATTERNS — don't reach for a plugin first
- **Don't add `SelectionPlugin` just to make a row clickable.** For "click row → open detail", listen for `cell-activate` (fires for pointer AND keyboard, so it's accessible for free). Add `SelectionPlugin` only for persistent visible selection state, checkboxes, or multi-select.
- **Don't write `cell-click`/`row-click` when you mean "activate".** Those are pointer-only — keyboard users won't trigger them. `cell-activate` is the unified, cancelable activation event. Use `cell-click` only when you specifically need pointer-only behaviour (e.g. left-vs-right button).
- **Don't subclass `BaseGridEditor` before trying `column.type`.** Built-in types (`'select'`, `'number'`, `'date'`, …) plus `gridConfig.typeDefaults` cover most editor needs. Subclass only for genuinely custom editor UI.
- **Don't reinvent post-render orchestration.** To act after first render (focus a cell, scroll to row, begin an edit), `await grid.ready()` instead of chaining `setTimeout`/`requestAnimationFrame`/`afterNextRender`.
A **framework-agnostic data grid** web component written in pure TypeScript, with no runtime dependencies. Import it, give it a height, and assign an array of rows.
## Quick Start
The grid ships as a standard custom element. Pick the install style that matches your setup.
#### With a bundler (Vite, webpack, etc.)
```bash
npm install @toolbox-web/grid
```
```typescript title="main.ts"
import '@toolbox-web/grid';
import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid('tbw-grid');
grid.columns = [
{ field: 'id', header: 'ID', type: 'number', sortable: true },
{ field: 'name', header: 'Name', sortable: true },
{ field: 'email', header: 'Email' },
];
grid.rows = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
{ id: 3, name: 'Carol', email: 'carol@example.com' },
];
```
```html title="index.html"
```
#### No build (CDN, single HTML file)
Drop one `
```
See the [Getting Started guide](https://toolboxjs.com/grid/getting-started.md) for framework integration (React, Vue, Angular), declarative HTML, plugins, and TypeScript setup.
### Live Demo
```ts
// IntroBasicDemo.astro
import '@toolbox-web/grid';
import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid('#demo-intro-basic');
if (grid) {
grid.columns = [
{ field: 'id', header: 'ID', type: 'number', sortable: true },
{ field: 'name', header: 'Name', sortable: true },
{ field: 'email', header: 'Email' },
];
grid.rows = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
{ id: 3, name: 'Carol', email: 'carol@example.com' },
{ id: 4, name: 'Dan', email: 'dan@example.com' },
{ id: 5, name: 'Eve', email: 'eve@example.com' },
];
}
```
## Architecture
Six patterns do most of the work:
| Pattern | What It Does |
| ------- | ------------ |
| **Centralized Render Scheduler** | Batches all updates into a single `requestAnimationFrame` per frame—no layout thrashing |
| **Phase-Based Execution** | Prioritizes work (config → rows → columns → render) for predictable updates |
| **DOM Recycling** | Reuses row elements via a pool with epoch-based invalidation—minimal GC pressure |
| **Template Cloning** | Pre-created templates cloned via `cloneNode(true)`—3-4x faster than `createElement` |
| **Event Delegation** | Single listener per event type on the container—scales to any dataset size |
| **Faux Scrollbar** | Separates scroll container from content—no reflow during scroll |
Read the full [Architecture deep-dive](https://toolboxjs.com/grid/architecture.md) for implementation details.
## Plugin System
The core grid is small. Everything beyond rendering, sorting and virtualization ships as a tree-shakeable plugin — import only what you need:
- **SelectionPlugin** — Cell, row, or range selection
- **FilteringPlugin** — Column header filters with custom panels
- **EditingPlugin** — Inline editing with built-in and custom editors
- **GroupingRowsPlugin** — Hierarchical row grouping with aggregations
- **TreePlugin** — Expandable tree data with lazy loading
- **MasterDetailPlugin** — Expandable detail rows
- **ExportPlugin** — CSV, Excel, or JSON export
- **ClipboardPlugin** — Copy/paste with Excel-compatible formatting
- ...and [many more](https://toolboxjs.com/grid/plugins.md)
Plugins get dependency validation, type-safe config extension, and auto-cleanup via `AbortSignal`. They use the same public API third parties do, so you can [build and distribute your own](https://toolboxjs.com/grid/plugin-development/custom-plugins.md).
## Next Steps
- [Getting Started](https://toolboxjs.com/grid/getting-started.md): Detailed setup for Vanilla JS, React, Vue, and Angular
- [Core Features](https://toolboxjs.com/grid/core.md): Sorting, rendering, keyboard navigation, and interactive playground
- [Plugins](https://toolboxjs.com/grid/plugins.md): Extend with selection, filtering, grouping, and 24+ more
- [API Reference](https://toolboxjs.com/grid/api-reference.md): Complete property, method, and event reference
---
---
# Getting Started
> Install @toolbox-web/grid and render your first grid in under a minute. Covers npm, CDN, ES modules, declarative HTML, and full framework integration for Vanilla JS, React, Vue, and Angular.
**Using a framework?** Jump directly to [Angular](https://toolboxjs.com/grid/angular/getting-started.md), [React](https://toolboxjs.com/grid/react/getting-started.md), or [Vue](https://toolboxjs.com/grid/vue/getting-started.md).
:::tip[Prefer declarative HTML with almost no JS?]
See [Plain JavaScript (No Build Step)](#plain-javascript-no-build-step) below for zero-JS setup with `@toolbox-web/grid/all`, declarative columns, template-based rendering/editing, and UMD script-tag usage.
:::
## Quick Start
1. **Install the package**
#### npm
```bash
npm install @toolbox-web/grid
```
#### yarn
```bash
yarn add @toolbox-web/grid
```
#### pnpm
```bash
pnpm add @toolbox-web/grid
```
#### bun
```bash
bun add @toolbox-web/grid
```
#### CDN
For quick prototyping, use the UMD bundle directly:
```html
```
2. **Import and use**
```typescript
import '@toolbox-web/grid'; // registers
import { queryGrid } from '@toolbox-web/grid'; // typed DOM helper
```
3. **Add the grid to your HTML**
```html
```
:::caution[The grid needs a height]
Set a height via CSS or inline style (e.g., `height: 400px`). Without it, the grid collapses to zero height and nothing will render. Use `height: auto` if you don't want virtual scrolling.
**Tip:** A parent CSS Grid or Flexbox layout that stretches the grid (e.g., a flex child with `flex: 1` or a grid row sized with `1fr`) also counts as a height — you don't need to set one explicitly on `` itself.
:::
### Declarative Columns (No JavaScript)
Define columns directly in HTML — great for static layouts and quick prototyping:
```html
```
Set `rows` from JavaScript or via the `rows` HTML attribute (JSON). See [Light DOM Columns](https://toolboxjs.com/grid/core.md#light-dom-columns) for the full attribute reference.
### Auto-Inferred Columns
Skip column configuration entirely — the grid creates columns from your data:
```typescript
import '@toolbox-web/grid';
import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid('#my-grid');
grid.rows = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com', active: true },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com', active: false },
];
// → Creates ID, Name, Email, and Active columns automatically
```
The grid detects types (`number`, `boolean`, `date`, `string`) from values and formats headers from field names (`firstName` → `First Name`). See [Column Inference](https://toolboxjs.com/grid/core.md#column-inference) for details.
## Framework Integration
The grid is a standard web component that works in any JavaScript environment — you can always use the Vanilla JS approach in any framework. For React, Vue, and Angular, we also provide dedicated adapter packages that enable custom component renderers and editors.
:::tip[Prefer a single `gridConfig` object]
Across every framework, the recommended pattern is to describe the grid with one `gridConfig` object — columns, `features`, and `plugins` together — and pass it as a single prop/input/attribute. Keep reactive data (`rows`) separate, since it changes independently of configuration.
A single config object is portable (the same `GridConfig` works in vanilla, React, Angular, and Vue), easy to share or snapshot in tests, and keeps multi-line feature config readable. Individual feature props (e.g. `selection="row"`) remain fully supported and are a fine shorthand for very small grids — but default to `gridConfig` for everything else, including any column that uses a custom renderer or editor.
For framework adapters (React/Vue/Angular), the default should be `gridConfig.features` rather than wiring many feature props/inputs/directives in templates. Keep those template-level bindings as shorthand for tiny examples.
:::
#### TypeScript
Add a grid element to your HTML, then configure it from JavaScript:
```html title="index.html"
```
```typescript title="main.ts"
import '@toolbox-web/grid';
import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid('tbw-grid');
grid.columns = [
{ field: 'id', header: 'ID', type: 'number' },
{ field: 'name', header: 'Name' },
{ field: 'email', header: 'Email' },
];
grid.rows = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com' },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com' },
{ id: 3, name: 'Carol White', email: 'carol@example.com' },
];
```
That's a working grid. From here, add features as you need them — sorting, editing, selection, and more are each a one-line import:
```typescript title="main.ts (with features)"
import '@toolbox-web/grid';
import { queryGrid } from '@toolbox-web/grid';
import '@toolbox-web/grid/features/editing';
import '@toolbox-web/grid/features/selection';
import '@toolbox-web/grid/features/filtering';
const grid = queryGrid('tbw-grid');
grid.gridConfig = {
columns: [
{ field: 'id', header: 'ID', type: 'number' },
{ field: 'name', header: 'Name', editable: true },
{ field: 'email', header: 'Email', editable: true },
],
features: {
editing: 'dblclick',
selection: 'row',
filtering: true,
},
};
grid.rows = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com' },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com' },
{ id: 3, name: 'Carol White', email: 'carol@example.com' },
];
grid.on('cell-commit', (detail) => console.log('Edited:', detail));
```
See [Core Features](https://toolboxjs.com/grid/core.md) for renderers, formatters, and custom editors.
:::note[Prefer creating grids programmatically?]
Use `createGrid()` to create a `` element without writing HTML:
```typescript
import { createGrid } from '@toolbox-web/grid';
const grid = createGrid({ columns: [...], features: { ... } });
document.body.appendChild(grid);
```
:::
#### React
For React projects, use the `@toolbox-web/grid-react` adapter so renderers and editors can be React components:
```bash
# Install both packages
npm install @toolbox-web/grid @toolbox-web/grid-react
```
```tsx title="EmployeeGrid.tsx"
import { DataGrid } from '@toolbox-web/grid-react';
const employees = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com' },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com' },
{ id: 3, name: 'Carol White', email: 'carol@example.com' },
];
function EmployeeGrid() {
return (
);
}
```
That's a working grid. From here, add features as you need them — each is a one-line import plus a prop:
```tsx title="EmployeeGrid.tsx (with features)"
import '@toolbox-web/grid-react/features/editing';
import '@toolbox-web/grid-react/features/selection';
import '@toolbox-web/grid-react/features/filtering';
import { DataGrid } from '@toolbox-web/grid-react';
const employees = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com' },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com' },
{ id: 3, name: 'Carol White', email: 'carol@example.com' },
];
function EmployeeGrid() {
return (
console.log('Edited:', e.detail)}
style={{ height: 400, display: 'block' }}
/>
);
}
```
The adapter adds JSX renderers/editors, the `useGrid` hook, and declarative `GridColumn` components.
See the [React adapter docs](https://toolboxjs.com/grid/react/getting-started.md) for custom renderers, editors, and the complete API reference.
#### Vue
For Vue projects, use the `@toolbox-web/grid-vue` adapter so renderers and editors can be Vue components or slots:
```bash
# Install both packages
npm install @toolbox-web/grid @toolbox-web/grid-vue
```
```html title="EmployeeGrid.vue"
```
That's a working grid. From here, add features as you need them — each is a one-line import plus a prop:
```html title="EmployeeGrid.vue (with features)"
console.log('Edited:', e.detail)"
style="height: 400px; display: block;"
/>
```
The adapter adds slot-based renderers/editors (`#cell`, `#editor`), the `useGrid` composable, and declarative `TbwGridColumn` components.
See the [Vue adapter docs](https://toolboxjs.com/grid/vue/getting-started.md) for custom renderers, editors, and the complete API reference.
#### Angular
For Angular projects, use the `@toolbox-web/grid-angular` adapter so renderers and editors can be Angular templates or components:
```bash
# Install both packages
npm install @toolbox-web/grid @toolbox-web/grid-angular
```
```typescript title="grid.component.ts"
import { Component } from '@angular/core';
import { Grid } from '@toolbox-web/grid-angular';
import type { ColumnConfig } from '@toolbox-web/grid-angular';
@Component({
selector: 'app-employee-grid',
imports: [Grid],
template: `
`,
})
export class EmployeeGridComponent {
employees = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com' },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com' },
{ id: 3, name: 'Carol White', email: 'carol@example.com' },
];
columns: ColumnConfig[] = [
{ field: 'id', header: 'ID', type: 'number' },
{ field: 'name', header: 'Name' },
{ field: 'email', header: 'Email' },
];
}
```
That's a working grid. From here, add features as you need them — each is a one-line import plus an input binding:
```typescript title="grid.component.ts (with features)"
import { GridEditingDirective } from '@toolbox-web/grid-angular/features/editing';
import { GridSelectionDirective } from '@toolbox-web/grid-angular/features/selection';
import { GridFilteringDirective } from '@toolbox-web/grid-angular/features/filtering';
import { Component } from '@angular/core';
import { Grid } from '@toolbox-web/grid-angular';
import type { ColumnConfig } from '@toolbox-web/grid-angular';
import type { CellCommitDetail } from '@toolbox-web/grid/plugins/editing';
@Component({
selector: 'app-employee-grid',
imports: [Grid, GridEditingDirective, GridSelectionDirective, GridFilteringDirective],
template: `
`,
})
export class EmployeeGridComponent {
employees = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com' },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com' },
{ id: 3, name: 'Carol White', email: 'carol@example.com' },
];
columns: ColumnConfig[] = [
{ field: 'id', header: 'ID', type: 'number' },
{ field: 'name', header: 'Name', editable: true },
{ field: 'email', header: 'Email', editable: true },
];
// camelCase outputs deliver the unwrapped detail directly ($event is the
// detail, not the native CustomEvent). Bind kebab-case (cell-commit) instead
// if you need the CustomEvent for event.preventDefault().
onCellCommit(detail: CellCommitDetail) {
console.log('Edited:', detail);
}
}
```
The adapter adds structural directives (`*tbwRenderer`, `*tbwEditor`), template-driven renderers/editors, and grid-level event outputs.
See the [Angular adapter docs](https://toolboxjs.com/grid/angular/getting-started.md) for custom renderers, editors, and the complete API reference.
## Plain JavaScript (No Build Step)
This section covers both no-build paths:
- ES module `/all` for declarative HTML-first setup
- UMD script tags with global `TbwGrid` for classic browser scripting
### HTML-first with `/all` (zero handwritten setup code)
Use this approach when you want a fully functional grid from plain HTML. The `/all` bundle auto-registers the grid plus all features/plugins, so you can configure everything with attributes and child elements.
:::caution[/all is convenience-first]
`@toolbox-web/grid/all` includes every plugin and feature. It is ideal for quick setup and HTML-first pages, but JS applications that care about bundle size should import only the features/plugins they use.
:::
#### Zero-JS Quickstart
1. Add the module script:
```html
```
2. Add a grid with JSON attributes:
```html
```
3. Interact with the grid:
- Sort by clicking any sortable header.
- Filter from header filter controls.
- Select rows.
- Edit `editable` cells (double-click in this example).
#### Declarative columns
Define columns with `` children. `field` is the only required attribute, and it
accepts the `field:type` shorthand — `field="price:number"` expands to `field="price"`,
`type="number"` and a generated header of "Price".
```html
```
Boolean attributes (`sortable`, `resizable`, `editable`, `hidden`, `lock-visible`) are enabled by
their presence. Some are contributed by plugins and only take effect when that plugin is
registered. For the complete attribute list, and for related declarative elements such as
`` and the shell/tool-panel elements, see
[API reference: Light DOM elements](https://toolboxjs.com/grid/api-reference.md#light-dom-elements).
#### Template rendering
Use `` for display and `` for custom editors.
Supported template expressions:
- `{{ value }}` for the current cell value.
- `{{ row.field }}` for other fields on the current row.
- Ternaries and simple expressions, for example `{{ row.status === 'active' ? 'ok' : 'bad' }}`.
Security boundaries:
- Script execution and event-handler attributes are not allowed in template output.
- HTML-string rendering is sanitized.
- Keep behavior wiring out of templates; these templates are for safe markup/data interpolation.
##### Live Demo
```ts
// HtmlOnlyUsageDemo.astro
import '@toolbox-web/grid/all';
```
This demo uses only declarative HTML and one `/all` script import. It includes a conditional badge class and a `