Skip to main content
/
/
/
Data Table

Data Table

Introduction

Gjallarbrú is a data grid component built on top of TanStack Table (GitHub) and MRT (GitHub) with Bifrost components. It supports a wide array of powerful datagrid features including, but not limited to:

  • Column
    • Hiding
    • Pinning
    • Reordering
    • Resizing
  • Row Expansion
  • Export
    • CSV
    • Excel
    • PDF
  • Filtering
    • Column Filters
    • Global Filter
  • Sorting
    • Multi-Column Sorting
  • Pagination
    • Page Size Options
  • Row Selection

It is also highly customizable and extensible aiming to fit any table use case.

It is easy to use, with sensible defaults and a simple column definition.

It is developed by Network Services Automation, and the code is in their monorepo. The component is published as a package in GitHub packages.

Beta

This component is currently considered "in beta". It is missing some important features, and might have some bugs.

Don't let this discourage you from using this component, it has already been used in production in Network Services' applications for almost a year, it is under active development and we are not planning any breaking changes to the prop API when exiting beta.

Note that the beta nature of this component is not reflected in the package version number or version tag.


Material React Table? TanStack? I thought this was Bifrost?

This doesn't work for me!

If something is not working as expected, or you are missing a feature, please create an issue, or upvote issues you think are important!

We want to make this package as useful as possible for everyone. But without your feedback, we can't know what to prioritize, or even what needs to be fixed, improved or implemented.

If you have questions, we encourage you to ask in #programming or #design on Slack, feel free to tag or contact any of the frontend developers in Network Services if you need help getting started, or have any questions about the package.

Install package

  1. Run the following command to install (requires access to npm.intility.com):
npm install @intility/gjallarbru
  1. Import component separately from other components
import { DataTable } from '@intility/gjallarbru'
Naming
  1. Use it in your JSX code
<DataTable columns={columns} data={data} name='Cats' />

There are three required props, columns, data and name.

Name should be unique per table in your application, as it is used for storing user preferences (column order, hidden columns, compact mode etc.) in local storage.

Kitchen Sink

This example showcases most of the common features, it is used throughout the documentation as a default example, and referred to as the "Kitchen Sink" example.

Name
Breed
Age
Birthdate
Last Checkup
Nationality
Microchip
Title
Identifier
Display Name
IP Address
Skills
Filter
Filter
Filter
Filter
Selkirk Rex
17
2008-02-08T18:48:47.009Z
2025-03-30T17:08:37.394Z
🇲🇵
Legacy Implementation Liaison
0
Aric35
177.221.104.53
Hunting
American Shorthair
3
2022-01-11T19:38:47.327Z
2025-09-20T18:22:06.143Z
🇵🇲
Principal Applications Developer
1
Jocelyn_Koelpin
183.178.38.10
Playing
Havana
17
2007-12-02T16:09:32.758Z
2025-03-27T23:53:33.990Z
🇳🇫
Investor Applications Administrator
2
Kathleen.Mosciski57
186.101.171.88
Hunting
Japanese Bobtail
2007-05-16T14:16:12.809Z
2025-07-02T10:03:51.929Z
🇬🇳
Internal Infrastructure Planner
3
Crystal49
a36a:a9ed:0bdc:1feb:1854:e72d:11a4:43cb
Purring
American Wirehair
20
2005-03-20T05:26:51.899Z
2025-11-01T17:56:07.953Z
🇰🇭
Customer Optimization Administrator
4
Beverly59
4b1b:da8f:8528:04a2:c454:39e4:da0f:b2bb
Climbing
Himalayan
2024-11-23T15:17:50.905Z
2025-02-26T09:06:36.021Z
🇻🇬
Forward Identity Assistant
5
May.Prosacco86
c73b:f2e2:f8db:0cef:aaa6:4d3c:8dcd:17e1
Sleeping
American Bobtail
12
2013-05-10T22:59:10.107Z
2025-03-20T13:16:31.031Z
🏴‍☠️
Legacy Group Manager
6
Audie.Hackett
193.225.156.126
Meowing
Exotic Shorthair
11
2014-02-03T02:29:26.148Z
2025-05-07T01:49:29.124Z
🇱🇹
International Mobility Architect
7
Christy.Bode-Lueilwitz11
203.128.8.19
Meowing
Peterbald
20
2025-01-08T03:41:04.126Z
🇺🇳
Chief Intranet Technician
8
Janae7
11.134.30.108
Jumping
American Shorthair
14
2011-05-14T02:26:51.612Z
2025-08-22T01:07:28.240Z
🇫🇷
Legacy Quality Analyst
9
Darrel.Simonis26
ae80:6f80:acc6:4188:fa52:edef:eefe:19f2
Scratching
Showing 1-10 of 1000
1 of 100......
10 Rows
Showing 1-10 of 1000
1 of 100......
10 Rows

Columns Definition

The columns definition is the core of any table, it defines what columns are in the table, how to access the data for each column, and what features each column should have.

The simplest column definition is just an array of objects with accessorKey and header properties:

const columns: Columns<Cat> = [
  {
    accessorKey: 'name',
    header: 'Name',
  },
]

If you're using TypeScript, you should type your column definition using Columns<TData> where TData is the type of your data rows:

import type { Columns } from '@intility/gjallarbru'

type Cat = {
  name: string
  age: number
}

const columns: Columns<Cat> = [
  {
    accessorKey: 'name',
    header: 'Name',
  },
  {
    accessorKey: 'age',
    filterVariant: 'select',
    header: 'Age',
  },
]

The data type could be an auto-generated DTO type from your backend API, or a manually defined type like in the example above.

Below you'll find the full columns definition used in the Kitchen Sink example above, it is also the basis for all examples throughout the docs.

It is meant to showcase a common set of features you might want to use in your own tables. In the feature specific documentation pages we will use simpler minimal examples with just one column definition to focus on the specific feature being documented.

Data Definition

You can access nested data using dot notation in the accessorKey property of your column definition.

Let's say breed was an object with name and origin properties instead of a simple string, you could access the breed name like this:

const data = [
  {
    name: 'Whiskers',
    breed: {
      name: 'Siamese',
      origin: 'Thailand',
    },
  },
  // more cats...
]

const columns: Columns<Cat> = [
  {
    accessorKey: 'breed.name',
    header: 'Breed',
  },
]

This works with any level of nesting, and the table gracefully handles missing keys in the nested structure.

I can't load all my data upfront!

If you have more complex data access needs, you can use the accessorFn property to provide a function that returns the value for the cell. In the Kitchen Sink example, Sex is stored as male or female, these values are not capitalized, so we use accessorFn to capitalize the value for display:

{
  accessorFn: row => capitalize(row.sex),
  header: 'Sex',
}

As you can see above, accessorFn receives the full row data as an argument, so you can access any part of the row to compute the value for the cell.

Known Bug

There is a known issue with accessorFn and loading state, where the accessorFn is called before the data is loaded, causing a crash if the function tries to access nested properties "unsafely". This will be fixed in the near future. (#1243)


Cells

While you can return JSX directly in the accessorFn, we generally do not recommend it. As it might have unexpected behaviour.

Instead, use the Cell key on the column definition to provide a custom cell renderer, you can read more about this in the Cells docs.

Below you'll find the full data definition used in the Kitchen Sink example above, it is also the basis for all examples throughout the docs. It uses Faker.js to generate data.