Skip to main content

cells

When creating tables in your application you'll probably want to customize how certain cells are rendered. By default, the table will render basic text cells, but you can easily override this behavior by providing custom cell types.

This is achieved through the Cell property on the column definition, which allows you to specify a custom cell renderer for that column. In the example below, we customize the "Microchip" column to render an icon indicating whether the cat has a microchip or not instead of just rendering "true" or "false" text.

const columns: Columns<Cat> = [
  {
    accessorKey: 'microchip',
    Cell: ({ cell }: { cell: MRT_Cell<Cat> }) => (
      <Icon
        color={cell.getValue() ? 'var(--bfc-success)' : 'var(--bfc-alert)'}
        icon={cell.getValue() ? faCircleCheck : faCircleX}
      />
    ),
    header: 'Microchip',
  },
]

The function you provide to the Cell receives lots of props that can be used to determine what you render with the most important ones probably being cell and row.

Below is an example with a full type definition for the Cell property:

import type { MRT_Cell, MRT_Column } from 'material-react-table'
import type { MRT_Row, MRT_TableInstance } from 'material-react-table'
import type { ReactNode, RefObject } from 'react'

const columns: Columns<Cat> = [
  {
    accessorKey: 'name',
    Cell: ({
      cell,
      column,
      renderedCellValue,
      row,
      rowRef,
      staticColumnIndex,
      staticRowIndex,
      table,
    }: {
      cell: MRT_Cell<Cat, string>
      column: MRT_Column<Cat, string>
      renderedCellValue: ReactNode
      row: MRT_Row<Cat>
      rowRef?: RefObject<HTMLTableRowElement | null>
      staticColumnIndex?: number
      staticRowIndex?: number
      table: MRT_TableInstance<Cat>
    }) => <div>Meow</div>,
    header: 'name',
  },
]

In most cases cell, row, and table will be sufficient to create custom cell renderers, but the other props are available if you need them.

Built-in Cell Types

To make development easier several built-in cell types are provided out-of-the-box.

And we have plans to add a bunch more in the future! Such as dates (#15), badges (#1148), buttons (#776) and more!

These cell types are exported from the main package as separate components that you can import and use in your column definitions. The built-in cell types integrate seamlessly with features like sorting, filtering, highlighting etc.

A common need when displaying tables is to have cells that can be clicked to navigate to other pages or routes in or outside your application. Several built-in cell types are provided to handle different navigation scenarios.

All these navigation cell types support styling and highlighting to match the rest of the table, and accept any props to the underlying link component, enabling you to customize them as needed.

The framework-specific link cell types (ReactRouterLinkCell and TSRLinkCell) obviously require that you have the respective routing library installed and set up in your application.

LinkCell

Renders a simple anchor (<a>) element for navigation to external URLs, with style matching and highlighting support.

const columns: Columns<Cat> = [
  {
    accessorKey: 'name',
    Cell: ({ cell, row }: { cell: MRT_Cell<Cat>; row: MRT_Row<Cat> }) => {
      const href = `https://www.google.com/search?q=${row.getValue<string>('breed')}+cat`
      return <LinkCell cell={cell} href={href} />
    },
    header: 'Name',
  },
]

This example is from the Kitchen Sink table, where the cat's name is a link to a Google search for the cat's breed.

ReactRouterLinkCell

Renders a React Router <Link> element for navigation within a React Router application.

const columns: Columns<Cat> = [
  {
    accessorKey: 'name',
    Cell: ({ cell, row }: { cell: MRT_Cell<Cat>; row: MRT_Row<Cat> }) => (
      <ReactRouterLinkCell cell={cell} to={row.original.id.toString()} />
    ),
    header: 'Name',
  },
]

TSRLinkCell

Renders a TanStack Router <Link> element for navigation within a TanStack Router application.

const columns: Columns<Cat> = [
  {
    accessorKey: 'name',
    Cell: ({ cell, row }: { cell: MRT_Cell<Cat>; row: MRT_Row<Cat> }) => (
      <TSRLinkCell cell={cell} to={row.original.id.toString()} />
    ),
    header: 'Name',
  },
]

ArrayCell

Sometimes your data may not be as flat as you wish, and you might have arrays that need to be displayed in a single cell. The ArrayCell component makes it easy to render arrays in table cells.

The first element of the array is always shown, and if there are more elements, a button with the count to expand the items.

import { arrayCellMultiSelectFilterFn, arrayCellSortingFn } from '@intility/gjallarbru'
const columns: Columns<Cat> = [
  {
    accessorKey: 'skills',
    Cell: ({ cell, table }: { cell: MRT_Cell<Cat>; table: MRT_TableInstance<Cat> }) => (
      <ArrayCell cell={cell} elements={cell.getValue<string[]>()} table={table} />
    ),
    filterFn: arrayCellMultiSelectFilterFn,
    filterVariant: 'multi-select',
    header: 'Skills',
    sortingFn: arrayCellSortingFn,
  },
]

In the example above, a custom sort and filter function is also used to enable sorting and filtering on the array values, you can of course provide your own custom implementations if needed, but these built-in functions should cover most use cases.

In the example below, no filterVariant is specified, so the default text filter is used instead, for array cells you can then use the built-in arrayCellTextFilterFn filter function to enable text filtering on the array values.

import { arrayCellSortingFn } from '@intility/gjallarbru'
const columns: Columns<Cat> = [
  {
    accessorKey: 'skills',
    Cell: ({ cell, table }: { cell: MRT_Cell<Cat>; table: MRT_TableInstance<Cat> }) => (
      <ArrayCell cell={cell} elements={cell.getValue<string[]>()} table={table} />
    ),
    filterFn: arrayCellTextFilterFn,
    header: 'Skills',
    sortingFn: arrayCellSortingFn,
  },
]

Helpers

When you use your own custom Cell: renderers, you loose some of the built-in functionality provided, such as text highlighting and truncation. To help with this, we provide some helper components that you can use within your custom cell renderers to easily add these features back in.

CellText

This component wraps the CellHighlight component and provides text truncation functionality through the Bifrost Ellipsis component.

You can pass it the cell prop, and it will automatically render the cell value with highlighting and truncation.

const columns: Columns<Cat> = [
  {
    accessorKey: 'name',
    Cell: ({ cell }: { cell: MRT_Cell<Cat> }) => (
      <>
        <CatPicture />
        <CellText cell={cell} />
      </>
    ),
    header: 'Name',
  },
]

You can also pass it children to customize the rendered value while still getting highlighting and truncation.

const columns: Columns<Cat> = [
  {
    accessorKey: 'name',
    Cell: ({ cell }: { cell: MRT_Cell<Cat> }) => (
      <>
        <CatPicture name={cell.getValue<string>()} />
        <CellText cell={cell}>Macavity, Macavity, there's no one like Macavity</CellText>
      </>
    ),
    header: 'Name',
  },
]

You can pass any children, but not everything will work as expected, as the highlighting and truncation functionality depends on the text content. For best results, pass plain text or rely on the default cell value rendering.

CellHighlight

If you don't want truncation, you can use the CellHighlight component to just get text highlighting for your custom cell renderers. It works exactly like CellText but without the truncation.

const columns: Columns<Cat> = [
  {
    accessorKey: 'name',
    Cell: ({ cell }: { cell: MRT_Cell<Cat> }) => (
      <>
        <CatPicture />
        <CellHighlight cell={cell} />
      </>
    ),
    header: 'Name',
  },
]

You can also customize how headers are rendered using the Header property on the column definition. It works similarly to the Cell property, allowing you to provide a custom header renderer for that column.

Here we also provide a helper component HeaderCell that you can use to get consistent styling and behavior for your custom headers. In the example below we customize the header for the "Name" column to render the text in red, with the HeaderCell component wrapping our custom content, while the "Breed" column header is customized without the helper component.

Because the Header override in the "Breed" column does not use the HeaderCell component, it loses a lot of features like column resizing, sorting, and column reordering support.

We generally recommend not to override the Header property unless you really need to, and if you do, use the HeaderCell component to ensure consistent behavior and styling.

const columns: Columns<Cat> = [
  {
    accessorKey: 'name',
    Header: ({ header, table }: { header: MRT_Header<Cat>; table: MRT_TableInstance<Cat> }) => (
      <HeaderCell header={header} table={table}>
        <div style={{ color: 'red' }}>Name</div>
      </HeaderCell>
    ),
    header: 'Name',
  },
  {
    accessorKey: 'breed',
    Header: ({ column }: { column: MRT_Column<Cat> }) => {
      return <div style={{ color: 'hotpink' }}>Breed</div>
    },
    header: 'Breed',
  },
]
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