DocsBlog
  • 1.0.0

  • light

    dark

    system

    Switch mode
  • Cerberus

    Acheron

    Elysium

Get Started
Components
Data Grid
Styling
Theming

Get Started

OverviewQuick StartColumnsContext

Layout

DimensionsSizingToolbarPagination

Features

PinningSorting

Reference

API

On this page

  • Edit this page on Github

Data Grid Quickstart

Learn how to use the Data Grid component in your React application.

  • source
import { DataGrid, createColumnHelper } from '@cerberus/data-grid';

Usage

Understanding the Data Grid

The Data Grid is a complex component that provides a wide range of features for displaying and interacting with data. It includes a variety of helpers to create an enhanced developer experience.

Step 1: The Data

The DataGrid accepts any form of data structures. Data is not what drives the component - defined columns are. All that matters for your data is that it is typed.

Step 2: Setup Columns

Columns are the engine that run the Data Grid.

Columns are defined using the createColumnHelper. This will provide a strictly typed interface for defining individual columns.

Pass in your data type to the createColumnHelper function and build your columns.

Creating Columns

Once you have setup your helper singleton, you can start building columns.

There are three methods available to create columns:

  • display: Non-interactive columns.
  • accessor: Interactive columns that utilize the features options.
  • accessorFn: Interactive columns that allow your to define custom logic for rendering cells.

You can learn more about the columns in on the Columns page.

Use the DataGrid

The final step is to add the DataGrid component to your application. You simply pass in the data, columns, and any other feature-related props.

Note

For contstrained layouts (seen in the demo preview), we recommend wrapping the DataGrid in a container that has a strict height defined.


The next pages cover each feature in detail.

Cerberus Design System | Docs
Copy
'use client'

import { DataGrid } from '@cerberus/data-grid'
import { HStack } from 'styled-system/jsx'
import { columns } from './columns.demo'
import { useFakeQuery } from './data'

export function BasicDemo() {
  // Normally this would be from useQuery or a server-side API call
  const data = useFakeQuery(1000)

  return (
    <HStack h="20rem" w="3/4">
      <DataGrid columns={columns} data={data} />
    </HStack>
  )
}
Copy
'use client'

import { DataGrid } from '@cerberus/data-grid'
import { HStack } from 'styled-system/jsx'
import { columns } from './columns.demo'
import { useFakeQuery } from './data'

export function BasicDemo() {
  // Normally this would be from useQuery or a server-side API call
  const data = useFakeQuery(1000)

  return (
    <HStack h="20rem" w="3/4">
      <DataGrid columns={columns} data={data} />
    </HStack>
  )
}
import { createColumnHelper } from '@cerberus/data-grid'
import { type Employee } from './data.demo'

export const columnHelper = createColumnHelper<Employee>()
'use client'

import { Edit } from '@carbon/icons-react'
import { Format, IconButton, Tag, TagProps, Text } from '@cerberus/react'
import { HStack, VStack } from 'styled-system/jsx'
import { columnHelper } from './helper.demo'

export const columns = [
  // A. "ID" Column that can be pinned and sorted
  columnHelper.accessor('id', {
    header: 'ID',
    width: 80,
    features: {
      pinning: {
        defaultPosition: 'left',
      },
      sort: true,
    },
    cell: ({ value }) => <Text>#{value}</Text>,
  }),

  // B. Derived Accessor (Function)
  // We combine First + Last name for sorting/filtering, but render custom UI
  columnHelper.accessorFn((row) => `${row.firstName} ${row.lastName}`, {
    id: 'fullName',
    header: 'Employee',
    width: 250,
    features: {
      sort: true,
      filter: { operator: 'contains' },
    },
    cell: ({ row, value }) => (
      <VStack alignItems="flex-start" gap="0">
        <Text textStyle="body-md">{value}</Text>
        <Text color="page.text.100" textStyle="label-sm">
          {row.email}
        </Text>
      </VStack>
    ),
  }),

  // C. Deep Accessor (Nested Object) using a plain text string for the cell
  columnHelper.accessorFn((row) => row.department.name, {
    id: 'department',
    header: 'Department',
    features: { sort: true },
  }),

  // D. Formatting (Numeric Sort, String Display)
  columnHelper.accessor('salary', {
    header: 'Salary',
    minWidth: 135,
    features: { sort: true }, // ✅ Sorts numerically (100 before 500)
    // We format the visual ONLY. The underlying data remains a number.
    cell: ({ value }) => (
      <Format.Number value={value} style="currency" currency="USD" />
    ),
  }),

  // E. Status Badge
  columnHelper.accessor('status', {
    header: 'Status',
    width: 110,
    features: {
      pinning: true,
    },
    cell: ({ value }) => {
      const palette: Record<string, TagProps['palette']> = {
        active: 'success',
        inactive: 'page',
        on_leave: 'info',
      }
      return (
        <Tag palette={palette[value]}>
          {value.replace('_', ' ').toUpperCase()}
        </Tag>
      )
    },
  }),

  // F. Display Column (Right Pinned Actions)
  columnHelper.display({
    id: 'actions',
    header: 'Actions',
    width: 125,
    features: {
      pinning: true,
    },
    cell: () => (
      <HStack justify="center" w="full">
        <IconButton ariaLabel="View more options">
          <Edit />
        </IconButton>
      </HStack>
    ),
  }),
]
export type Employee = {
  id: number
  firstName: string
  lastName: string
  email: string
  status: 'active' | 'inactive' | 'on_leave'
  salary: number
  department: {
    name: string
    code: string
  }
  lastLogin: string
}