---
id: "packages/active-grid/getting-started"
title: "Getting started"
description: "Receive active-grid with its owners, import the stylesheet, and render a first grid."
url: "/packages/active-grid/getting-started"
locale: "en"
revision: "21ff8550d8381d89"
---

# Getting started

## Receive the package

`active-grid` is a product. Its owners `active-format`, `active-virtual` and `active-helpers` come
along in the same bundle. Ask the maintainer of Foundation for a bundle of your whole managed set,
then follow [Receiving packages](/receiving-packages):

```bash
node tools/rps/rps-apply.mjs plan --bundle <bundle-folder> --development
node tools/rps/rps-apply.mjs apply --bundle <bundle-folder> --expect-plan <digest> --development
```

Read the plan before you apply it: `removed: -`, unless you mean to drop a package.

## Declare, install and verify

```json
{
  "dependencies": {
    "@workspace/active-format": "workspace:*",
    "@workspace/active-grid": "workspace:*",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  }
}
```

```bash
pnpm install
node tools/rps/rps-apply.mjs verify-install --from <app-folder>
```

In Next.js, list `@workspace/active-grid` and its owners in `transpilePackages`. For TypeScript,
your app needs a declaration for CSS imports (`declare module '*.css';`) if its setup has none. If
you leave out the optional export libraries, tell your bundler they are external.

## A first grid

```tsx
'use client';

import '@workspace/active-grid/styles.css';

import {
  ActiveGrid,
  createColumnHelper,
  englishGridTranslator,
  GridDefaults,
  type GridColumnDef,
} from '@workspace/active-grid';

type Person = {id: string; name: string; email: string};

const ch = createColumnHelper<Person>();
const columns: GridColumnDef<Person>[] = [
  ch.accessor('name', {header: 'Name', meta: {filterType: 'text'}}),
  ch.accessor('email', {header: 'Email', meta: {filterType: 'text'}}),
];

export function People({people}: {people: Person[]}) {
  return (
    <GridDefaults locale="en-GB" t={englishGridTranslator}>
      <ActiveGrid
        gridId="people"
        mode="client"
        data={people}
        columns={columns}
        height="auto"
      />
    </GridDefaults>
  );
}
```

`locale` is a language tag or a presentation built with active-format's
`composePresentationContext`. Relative date presets, the date-filter calendar and `dateTime`
filters need a time zone in it.

**Example: Orders in client mode**

Client: Runs entirely in your browser. Source: `examples/grid/client-orders.tsx`.

```tsx
// apps/docs/examples/grid/client-orders.tsx
'use client';

import '@workspace/active-grid/styles.css';

import {useMemo} from 'react';
import {generateOrders, type Order} from '@/lib/examples/orders';

import {
  composePresentationContext,
  toIanaTimeZone,
} from '@workspace/active-format';
import {
  ActiveGrid,
  createColumnHelper,
  englishGridTranslator,
  type GridColumnDef,
} from '@workspace/active-grid';

// The presentation: language, notation and the time zone the date filter
// needs for its relative presets and calendar.
const presentation = composePresentationContext(
  'en-GB',
  null,
  toIanaTimeZone('Europe/Amsterdam'),
);

const STATUS = [
  {label: 'Pending', value: 'pending'},
  {label: 'Processing', value: 'processing'},
  {label: 'Shipped', value: 'shipped'},
  {label: 'Delivered', value: 'delivered'},
  {label: 'Cancelled', value: 'cancelled'},
];

const ch = createColumnHelper<Order>();
const columns: GridColumnDef<Order>[] = [
  ch.accessor('id', {header: 'Order', meta: {filterType: 'text'}}),
  ch.accessor('customer', {header: 'Customer', meta: {filterType: 'text'}}),
  ch.accessor('category', {
    header: 'Category',
    meta: {filterType: 'select'},
  }),
  ch.accessor('quantity', {header: 'Qty', type: 'number'}),
  ch.accessor('total', {
    header: 'Total',
    type: 'currency',
    meta: {currencyCode: 'EUR', filterType: 'number'},
  }),
  ch.accessor('orderDate', {header: 'Ordered', type: 'date'}),
  ch.accessor('status', {
    header: 'Status',
    type: 'badge',
    meta: {
      filterType: 'select',
      filterOptions: STATUS,
      statusTones: {
        pending: 'warning',
        processing: 'info',
        shipped: 'info',
        delivered: 'success',
        cancelled: 'danger',
      },
    },
  }),
];

/** Client mode: all 500 rows are in the browser; the grid sorts, filters and pages them there. */
export default function ClientOrders() {
  const data = useMemo(() => generateOrders(500), []);
  return (
    <ActiveGrid<Order>
      gridId="docs-client-orders"
      mode="client"
      data={data}
      columns={columns}
      height={420}
      locale={presentation}
      t={englishGridTranslator}
      enableRowSelection
      pagination={{enabled: true, pageSizeOptions: [10, 25, 50]}}
      toolbar={{search: {enabled: true}, showColumnChooser: true}}
    />
  );
}
```

## Map the tokens (optional)

The grid looks neutral until your application maps its `--grid-*` role tokens to your own; see
[Host styling](/packages/active-grid/host-styling).

## Next

[Client, server and simulation](/packages/active-grid/client-server-and-simulation) shows server
mode against a real route.
