Colors

The react-bootstrap-data-grid grid component supports changing the background colors of grid cells according to Bootstrap color variants. This manner of applying color variants is designed to be similar to the way that Bootstrap supports applying color variants to tables.

Granularity

The react-bootstrap-data-grid grid supports applying color variants at varying levels of granularity: from selecting a color variant for the entire grid to differing variants for each individual cell.

More specific variant settings can override less specific ones. For example, a grid-wide variant will be overridden by a setting for a row, which will in turn be overridden by the settings for specific cells.

Additionally, one can set a color variant for a grid's borders in a manner similar to that of Bootstrap tables.

The following sections describe each level of granularity available:

Grid-wide

One can set the color variant for the entire grid by passing a value to the variant prop of the Grid component. The result on the styling to the grid is similar to using a table variant Bootstrap CSS class on the HTML table element.

Header Row

Set the headerRowVariant prop on the Grid component to set the color variant on the header row of the grid. There is only one header row for a grid, so this prop takes a single string value that applies to that row.

Header Cell

One can customize the color variant on individual header cells by passing a function as the headerCellVariant prop on the Grid component.

Parameters passed to the function include the column definition (ColDef) and the column index (zero-based starting on the left). The function can either return a string that is the color variant or null. When null is returned, the color scheme of the cell will inherit the color scheme of the header row, which in turn may inherit the grid-wide setting.

Body Row

One can set the color variant on a per-row basis in the grid's body by passing a function to the bodyRowVariant prop on the Grid component.

A grid often contains more than one body row. For that reason, two parameters are passed into the function to provide details about each row. The first parameter is a detailed object of type FormattedRow that includes the contents of each cell in the row. The second parameter is the zero-based index of the row starting from the top of the grid body.

The function can return a string that is color variant or null to have the row inherit the color scheme from the grid-wide setting.

Body Cell

One can set the color variant on a per-cell basis in the grid's body by passing a function to the bodyCellVariant prop on the Grid component.

The function takes 4 parameters:

  1. Contents and metadata for the cell. Type of the parameter is CellData.
  2. Contents and metadata for the entire row. Type of the parameter is FormattedRow.
  3. The zero-based column index starting from the left
  4. THe zero-based row index starting from the top of the grid body

For cells where the function returns null the color scheme will be inherited from the body row.

Borders

Border color can be set in two ways. The first is that when one sets a grid-wide color variant, the border color for the grid will change to a color that is derived (via Sass color processing functions) from the variant color.

This border color can additionally be overridden by separate border variant color setting. When the borderVariant prop on the Grid component is set, the component will apply a Bootstrap border color utility to the grid.

Example

The following code sample interactively demonstrates the different color variant settings described earlier in the article.

Live Demo

Name
Primary Attribute
Saving Throw Proficiencies
Spellcasting Ability
Armor Proficiency
Barbarian
Strength
Strength, Constitution
Charisma
Medium
Bard
Charisma
Charisma, Dexterity
Charisma
Light
Cleric
Wisdom
Wisdom, Charisma
Wisdom
Medium
Druid
Wisdom
Wisdom, Intelligence
Wisdom
Medium
Fighter
Strength
Strength, Constitution
Intelligence
Heavy
Monk
Dexterity
Dexterity, Strength
Wisdom
None
Paladin
Strength
Wisdom, Charisma
Charisma
Heavy
Ranger
Dexterity
Dexterity, Strength
Wisdom
Medium
Rogue
Dexterity
Dexterity, Intelligence
Intelligence
Light
Sorcerer
Charisma
Charisma, Constitution
Charisma
None
Warlock
Charisma
Charisma, Wisdom
Charisma
Light
Wizard
Intelligence
Intelligence, Wisdom
Intelligence
None

Code

"use client";
 
import Grid, {
  GridProps,
  RowDef,
  ColDef,
} from "@absreim/react-bootstrap-data-grid/grid";
import { FC, ReactNode, useState } from "react";
import Form from "react-bootstrap/Form";
import Stack from "react-bootstrap/Stack";
 
// --- Sample data ---
 
 
interface Bg3Class {
  name: string;
  primaryAttribute: string;
  savingThrowProficiencies: string;
  spellcastingAbility: string;
  armorProficiency: string;
}
 
const cols: ColDef[] = [
  {
    name: "name",
    label: "Name",
    type: "string",
  },
  {
    name: "primaryAttribute",
    label: "Primary Attribute",
    type: "string",
    width: 200,
  },
  {
    name: "savingThrowProficiencies",
    label: "Saving Throw Proficiencies",
    type: "string",
    width: 250,
  },
  {
    name: "spellcastingAbility",
    label: "Spellcasting Ability",
    type: "string",
    width: 200,
  },
  {
    name: "armorProficiency",
    label: "Armor Proficiency",
    type: "string",
    width: 200,
  },
];
 
const rows: RowDef<Bg3Class>[] = [
  {
    id: "barbarian",
    data: {
      name: "Barbarian",
      primaryAttribute: "Strength",
      savingThrowProficiencies: "Strength, Constitution",
      spellcastingAbility: "Charisma",
      armorProficiency: "Medium",
    },
  },
  {
    id: "bard",
    data: {
      name: "Bard",
      primaryAttribute: "Charisma",
      savingThrowProficiencies: "Charisma, Dexterity",
      spellcastingAbility: "Charisma",
      armorProficiency: "Light",
    },
  },
  {
    id: "cl" + "eric",
    data: {
      name: "Cleric",
      primaryAttribute: "Wisdom",
      savingThrowProficiencies: "Wisdom, Charisma",
      spellcastingAbility: "Wisdom",
      armorProficiency: "Medium",
    },
  },
  {
    id: "druid",
    data: {
      name: "Druid",
      primaryAttribute: "Wisdom",
      savingThrowProficiencies: "Wisdom, Intelligence",
      spellcastingAbility: "Wisdom",
      armorProficiency: "Medium",
    },
  },
  {
    id: "fighter",
    data: {
      name: "Fighter",
      primaryAttribute: "Strength",
      savingThrowProficiencies: "Strength, Constitution",
      spellcastingAbility: "Intelligence",
      armorProficiency: "Heavy",
    },
  },
  {
    id: "monk",
    data: {
      name: "Monk",
      primaryAttribute: "Dexterity",
      savingThrowProficiencies: "Dexterity, Strength",
      spellcastingAbility: "Wisdom",
      armorProficiency: "None",
    },
  },
  {
    id: "paladin",
    data: {
      name: "Paladin",
      primaryAttribute: "Strength",
      savingThrowProficiencies: "Wisdom, Charisma",
      spellcastingAbility: "Charisma",
      armorProficiency: "Heavy",
    },
  },
  {
    id: "ranger",
    data: {
      name: "Ranger",
      primaryAttribute: "Dexterity",
      savingThrowProficiencies: "Dexterity, Strength",
      spellcastingAbility: "Wisdom",
      armorProficiency: "Medium",
    },
  },
  {
    id: "rogue",
    data: {
      name: "Rogue",
      primaryAttribute: "Dexterity",
      savingThrowProficiencies: "Dexterity, Intelligence",
      spellcastingAbility: "Intelligence",
      armorProficiency: "Light",
    },
  },
  {
    id: "sorcerer",
    data: {
      name: "Sorcerer",
      primaryAttribute: "Charisma",
      savingThrowProficiencies: "Charisma, Constitution",
      spellcastingAbility: "Charisma",
      armorProficiency: "None",
    },
  },
  {
    id: "warlock",
    data: {
      name: "Warlock",
      primaryAttribute: "Charisma",
      savingThrowProficiencies: "Charisma, Wisdom",
      spellcastingAbility: "Charisma",
      armorProficiency: "Light",
    },
  },
  {
    id: "wizard",
    data: {
      name: "Wizard",
      primaryAttribute: "Intelligence",
      savingThrowProficiencies: "Intelligence, Wisdom",
      spellcastingAbility: "Intelligence",
      armorProficiency: "None",
    },
  },
];
 
// --- Form elements ---
 
const variants: string[] = [
  "primary",
  "secondary",
  "success",
  "warning",
  "danger",
  "info",
  "light",
  "dark",
];
 
const headerCellsFn: GridProps["headerCellVariant"] = (_, colIndex) => {
  if (colIndex % 2 === 0) {
    return "primary";
  }
 
  return null;
};
 
const bodyRowsFn: GridProps["bodyRowVariant"] = (_, displayIndex) => {
  if (displayIndex % 2 === 0) {
    return "success";
  }
 
  return null;
};
 
const bodyCellsFn: GridProps["bodyCellVariant"] = (
  _,
  __,
  colIndex,
  displayIndex,
) => {
  if (colIndex === displayIndex) {
    return "info";
  }
 
  return null;
};
 
const useVariantDropdown: (
  name: string,
  label: string,
) => { selectUi: ReactNode; propValue: string | undefined } = (name, label) => {
  const [stateVal, setStateVal] = useState<string>("");
 
  const id = `${name}-settingDropdown`;
  const selectUi = (
    <div>
      <label htmlFor={id}>{label}</label>
      <Form.Select
        id={id}
        value={stateVal}
        onChange={({ target }) => setStateVal(target.value)}
      >
        <option value="">(None)</option>
        {variants.map((variant) => (
          <option key={variant} value={variant}>
            {variant}
          </option>
        ))}
      </Form.Select>
    </div>
  );
  const propValue = stateVal === "" ? undefined : stateVal;
 
  return {
    selectUi,
    propValue,
  };
};
 
const useToggleSwitch: (
  name: string,
  label: string,
) => { switchUi: ReactNode; enabled: boolean } = (name, label) => {
  const [enabled, setEnabled] = useState<boolean>(false);
  const switchUi = (
    <Form.Check
      id={`${name}-settingToggle`}
      type="switch"
      label={label}
      checked={enabled}
      onChange={({ target }) => setEnabled(target.checked)}
    />
  );
 
  return {
    switchUi,
    enabled,
  };
};
 
// --- Demo component ---
 
const ColorSettingsDemo: FC = () => {
  const gridVariant = useVariantDropdown("grid", "Grid-wide Variant");
  const headerRowVariant = useVariantDropdown(
    "headerRow",
    "Header Row Variant",
  );
  const borderVariant = useVariantDropdown("border", "Border Variant");
  const headerCells = useToggleSwitch(
    "headerCells",
    "Enable Header Cell Variants",
  );
  const bodyRows = useToggleSwitch("bodyRows", "Enable Body Row Variants");
  const bodyCells = useToggleSwitch("bodyCells", "Enable Body Cell Variants");
 
  return (
    <Stack gap={2}>
      {gridVariant.selectUi}
      {headerRowVariant.selectUi}
      {borderVariant.selectUi}
      {headerCells.switchUi}
      {bodyRows.switchUi}
      {bodyCells.switchUi}
      <Grid
        width="parent"
        rows={rows}
        cols={cols}
        variant={gridVariant.propValue}
        headerRowVariant={headerRowVariant.propValue}
        borderVariant={borderVariant.propValue}
        headerCellVariant={headerCells.enabled ? headerCellsFn : undefined}
        bodyRowVariant={bodyRows.enabled ? bodyRowsFn : undefined}
        bodyCellVariant={bodyCells.enabled ? bodyCellsFn : undefined}
      />
    </Stack>
  );
};
 
export default ColorSettingsDemo;