Themes & Color Mode

react-data-table-component ships with a set of built-in structural themes and a flexible theming system built on CSS custom properties. Pick a named theme with the theme prop, brand any theme with createTheme(), and let colorMode handle light/dark automatically.

Built-in themes

Select a theme and color mode. Structural themes define density, spacing, and shape. colorMode controls light/dark.

Theme
Color modefollows the page toggle above
Name
Department
Salary
Aria Chen
Engineering
$155,000
Marcus Webb
Product
$132,000
Priya Kapoor
Design
$118,000
Jordan Ellis
Analytics
$143,000
Sam Rivera
Engineering
$128,000

Structural themes

Structural themes define density, spacing, typography, and shape. They ship with a neutral palette that adapts to light and dark mode via colorMode. Brand them with createTheme() to add your own accent color:

// Apply Material Design layout with your own brand color
createTheme('material-violet', { primary: '#6200EE' }, 'material');

<DataTable columns={columns} data={data} theme="material-violet" />
NameDensityShapeSeparator defaults
default 48 px rows, 16 px padding 4 px radius Header separator on, no column separators
material 52 px rows, 16 px padding 4 px radius No header or column separators (Material uses row dividers only)
rounded 48 px rows, 18 px padding 8 px radius, circular checkboxes Subtle header separator
catppuccin 48 px rows, 16 px padding 6 px radius Subtle header separator, Catppuccin Latte (light) / Mocha (dark)
crisp 42 px rows, 16 px padding 4 px radius Subtle header separator (AG Grid Quartz)

All themes include a darkMode block and respond correctly to colorMode="system" or colorMode="dark".

colorMode

The colorMode prop controls whether DataTable applies the active theme's darkMode overrides.

ValueBehavior
"light" Always render in light mode regardless of OS preference or page class.
"dark" Always render in dark mode, applying the theme's darkMode overrides.
"system" (default) Follow the page automatically. DataTable checks, in order:
  1. localStorage.getItem('theme'): your app's stored preference
  2. The html.dark class: set by most dark-mode toggle libraries
  3. prefers-color-scheme: dark: the OS preference
It reacts in real time to all three using a MutationObserver and a storage event listener, so DataTable updates when the user toggles the page theme without needing a re-render from outside.
// Always dark — ignores OS preference
<DataTable columns={columns} data={data} theme="material" colorMode="dark" />

// Follow OS / page toggle (default, explicit)
<DataTable columns={columns} data={data} theme="crisp" colorMode="system" />

// Force light even when the page is in dark mode
<DataTable columns={columns} data={data} theme="rounded" colorMode="light" />

createTheme()

createTheme() accepts two call signatures:

import { createTheme } from 'react-data-table-component';

// 1. Named — register globally, reference by string in the theme prop
createTheme('my-brand', { primary: '#6200EE' }, 'material');

// 2. Inline — compose and pass the object directly to the theme prop
const inlineTheme = createTheme({ primary: '#e91e63' }, 'crisp');
<DataTable theme={inlineTheme} columns={columns} data={data} />

Theme shape

All keys are optional. Unspecified fields inherit from the base theme. For darkMode, supply only the fields that differ from light mode; they are merged on top of the light values at render time.

import { createTheme } from 'react-data-table-component';

createTheme('violet', {
  primary: '#6200EE',
  text: {
    primary: '#1a1a2e',
    secondary: '#4a4a6a',
    disabled: '#9e9e9e',
  },
  background: {
    default: '#f5f0ff',
    header: '#ede7f6',   // distinct header background
  },
  divider:          { default: '#d1c4e9' },
  selected:         { default: '#ede7f6', text: '#1a1a2e' },
  highlightOnHover: { default: '#ede7f6', text: '#1a1a2e' },
  striped:          { default: '#f3eeff', text: '#1a1a2e' },
  button: {
    default: '#6200EE',
    focus:    'rgba(98,0,238,0.12)',
    hover:    'rgba(98,0,238,0.08)',
    disabled: '#d1c4e9',
  },
  context: { background: '#6200EE', text: '#ffffff' },
  // Dark-mode overrides — only what changes
  darkMode: {
    primary: '#BB86FC',
    text:       { primary: '#e0e0e0', secondary: '#b0b0b0' },
    background: { default: '#1a0533', header: '#240844' },
    divider:    { default: '#3d1f6e' },
    selected:   { default: '#2d1060', text: '#e0e0e0' },
    highlightOnHover: { default: '#2d1060', text: '#e0e0e0' },
    striped:    { default: '#1e0a40', text: '#e0e0e0' },
  },
  // Structural
  spacing:    { rowHeight: '48px', headerHeight: '56px', cellPaddingX: '16px' },
  typography: { fontSize: '14px', fontSizeHeader: '12px' },
  shape:      { borderRadius: '8px' },
});

Icons

Sort chevron, row expander, and pagination arrows can all be replaced. There are two ways: bake them into a theme so every table using it gets them automatically, or pass them as per-table props for a one-off override. Props win when both are set.

Override via props

Pass icons directly on a single table. Only the icons you supply are replaced. The rest fall back to the theme or built-in defaults.

import { ChevronUp, ChevronDown, ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-react';

// Sort icon — replaces the chevron shown in sortable column headers
<DataTable
  sortIcon={<ChevronUp size={14} />}
  columns={columns}
  data={data}
/>

// Expander icons — collapsed / expanded state
<DataTable
  expandableRows
  expandableIcon={{
    collapsed: <ChevronDown size={16} />,
    expanded:  <ChevronUp  size={16} />,
  }}
  columns={columns}
  data={data}
/>

// Pagination icons — any subset; omitted keys fall back to defaults
<DataTable
  pagination
  paginationIcons={{
    previous: <ChevronLeft  size={16} />,
    next:     <ChevronRight size={16} />,
    first:    <ChevronsLeft  size={16} />,
    last:     <ChevronsRight size={16} />,
  }}
  columns={columns}
  data={data}
/>

Override via theme

Declare icons inside a theme so every table using it shares the same iconography without repeating props. Per-table props override the theme when explicitly passed.

import { createTheme } from 'react-data-table-component';
import { ChevronUp, ChevronDown, ChevronLeft, ChevronRight } from 'lucide-react';

createTheme('icon-theme', {
  icons: {
    sort: <ChevronUp size={14} />,
    expandable: {
      collapsed: <ChevronDown size={16} />,
      // expanded: omitted — falls back to the built-in default
    },
    pagination: {
      next:     <ChevronRight size={16} />,
      previous: <ChevronLeft size={16} />,
      // first/last: omitted — fall back to defaults
    },
  },
});

<DataTable columns={columns} data={data} theme="icon-theme" />

Custom checkbox component

Replace the built-in checkbox with your own component via selectableRowsComponent. Extra props can be forwarded through selectableRowsComponentProps. The component receives standard HTMLInputElement props and a ref. DataTable sets el.indeterminate directly on the ref to handle the partial-selection state.

import Checkbox from '@mui/material/Checkbox';

<DataTable
  selectableRows
  selectableRowsComponent={Checkbox}
  selectableRowsComponentProps={{ color: 'primary' }}
/>

If you build your own checkbox, use React.forwardRef and forward the ref to the underlying <input> element so DataTable can set indeterminate natively:

import React from 'react';

const MyCheckbox = React.forwardRef<
  HTMLInputElement,
  React.InputHTMLAttributes<HTMLInputElement>
>((props, ref) => (
  <input
    {...props}
    ref={ref}
    style={{ accentColor: 'teal', width: 18, height: 18 }}
  />
));
MyCheckbox.displayName = 'MyCheckbox';

<DataTable
  selectableRows
  selectableRowsComponent={MyCheckbox}
/>

Header & column separators in themes

The headerSeparator and columnSeparator props can be baked into a theme so every table using it shares the same separator style. The per-table prop always takes precedence when explicitly passed.

createTheme('grid', {
  primary: '#1976d2',
  headerSeparator: 'full',   // bold line below header row
  columnSeparator: 'full',   // full-height lines between columns
}, 'default');

// Override for one specific table
<DataTable theme="grid" columnSeparator={false} />

Column separators

Toggle between no separators, subtle inset lines, and full-height lines.

Body separators:Inset 60%-height
Header separators:Inset 60%-height (default)
Name
Department
Salary
Aria Chen
Engineering
$155,000
Marcus Webb
Product
$132,000
Priya Kapoor
Design
$118,000
Jordan Ellis
Analytics
$143,000
Sam Rivera
Engineering
$128,000

CSS variable override

Every theme compiles to CSS custom properties scoped to DataTable's wrapper element. Override any variable with a wrapper class. No createTheme() needed for small tweaks.

.my-table {
  --rdt-color-text-primary:   #1a1a2e;
  --rdt-color-bg:             #f0f4ff;
  --rdt-color-header-bg:      #e8edff;  /* separate header background */
  --rdt-color-divider:        #c7d2fe;
  --rdt-color-highlight:      #e0e7ff;
  --rdt-color-selected:       #ede9fe;
  --rdt-border-radius:        8px;
  --rdt-font-size:            13px;
}

CSS variable reference

VariableDefaultWhat it controls
--rdt-color-schemelightCSS color-scheme: affects native checkbox, select, and scrollbar rendering
--rdt-color-primary#1976d2Checkbox accent, active sort icon, selection ring
--rdt-color-text-primaryrgba(0,0,0,.87)Primary text in rows and header cells
--rdt-color-text-secondaryrgba(0,0,0,.54)Muted text: group labels, pagination count
--rdt-color-text-disabledrgba(0,0,0,.38)Disabled row text
--rdt-color-bg#fffTable and row background
--rdt-color-header-bgfalls back to --rdt-color-bgHeader row background: set only when the theme or CSS provides it
--rdt-color-dividerrgba(0,0,0,.12)Row borders and separator lines
--rdt-color-context-bg#e3f2fdSelected-rows context bar background
--rdt-color-context-textrgba(0,0,0,.87)Selected-rows context bar text
--rdt-color-selected#e3f2fdSelected row background
--rdt-color-selected-textrgba(0,0,0,.87)Selected row text
--rdt-color-highlight#eeeHover highlight background
--rdt-color-highlight-textrgba(0,0,0,.87)Hover highlight text
--rdt-color-striped#fafafaStriped (even) row background
--rdt-color-striped-textrgba(0,0,0,.87)Striped row text
--rdt-color-btnrgba(0,0,0,.54)Sort icon, expander chevron, pagination button icons
--rdt-color-btn-hoverrgba(0,0,0,.08)Pagination button hover background
--rdt-color-btn-focusrgba(0,0,0,.12)Pagination button focus ring
--rdt-color-btn-disabledrgba(0,0,0,.18)Disabled pagination button icon
--rdt-row-height52pxBody row min-height
--rdt-header-height56pxHeader row min-height
--rdt-cell-padding-x16pxHorizontal padding inside every cell
--rdt-font-size13pxBody cell font size
--rdt-font-size-header12pxHeader cell font size
--rdt-font-familyinheritsFont family for all table text
--rdt-border-radius4pxPill radius on selection badges and other rounded elements

Prop reference

PropTypeDefaultDescription
theme string | Theme | Record<string, string> "default" Named built-in theme, a Theme object from createTheme(overrides, inherit), or a raw CSS variable map ({ '--rdt-color-bg': '#000', ... }).
colorMode "light" | "dark" | "system" "system" Controls when the theme's darkMode overrides are applied. "system" follows localStorage, the html.dark class, then prefers-color-scheme.
selectableRowsComponent React.ComponentType<InputHTMLAttributes> | "input" "input" Custom checkbox component. Must accept standard input props and forward its ref to an <input> element so DataTable can set indeterminate.
selectableRowsComponentProps Record<string, unknown> - Extra props forwarded to every instance of the custom checkbox component.
headerSeparator boolean | "full" theme default or true Line below the header row. true = subtle inset line. "full" = full-height divider. false = none. Overrides the theme's headerSeparator setting.
columnSeparator boolean | "full" theme default or false Vertical lines between body row cells. true = subtle inset. "full" = full-height. false = none. Overrides the theme's columnSeparator setting.
customStyles TableStyles - Fine-grained style overrides per slot (rows, cells, header, pagination, etc.). Applied on top of the active theme. See the Custom Styles page.