Search
Matt Glissmann

Dark Mode Theming in Grommet - Part 3: Theme color customization

December 15, 2023

g1lightdark3_1

This is the final post in a three-part series. Parts 1 and 2 introduced how to apply a theme, change the theme’s mode between light and dark, and, finally, provide an app’s user the ability to change the theme’s mode to their preference.

In this final post, I’ll demonstrate how to add custom light and dark mode colors to the theme. I will cover the following content:

  • Creating a custom theme file
  • Defining the color palette
  • Mapping the color palette to component definitions in the theme
  • Merging the customizations with an existing theme

Customizing the Theme

Up to this point, we have been using Grommet’s theme. Let’s say, however, we’d like to tweak the Grommet theme by adding some custom colors for my fictional company, Acme, Inc.

To do this, continue modifying your app from where Part 2 concluded, or reference this Codesandbox if you are catching up and joining midstream.

Acme’s brand colors are Ruby, Gold, and Amethyst, with some warm greys for backgrounds and text. The hex values for Acme’s color palette, plus values for the light and dark variants, are provided below.

g3 table

To begin the custom Acme, Inc. theme, create a theme file, define the color palette, and then map the color palette to the Grommet components for which you want the colors to be applied.

Create Theme File

In the src directory, create a theme file called acme-theme.js with the theme object acme as an export:

g2part 3 image

Define the Color Palette

Define the color palette by naming each color, plus their dark and light variants. Colors are defined in the theme object’s global.colors property. For each color, the following structure is used:

uniqueColorName: {
    dark: ‘hexidecimal value or reference a color name’,
    light: ‘hexidecimal value or reference a color name’,
},
uniqueColorName! : ‘hexidecimal value or reference a color name’,

Notice that any Grommet component with color as an attribute can accept either a string or an object containing dark and light properties. Dark specifies the color Grommet uses when the element is on a dark background; light specifies the color for use on a light background.

Additionally, by convention, a color name followed by a ‘!’ bang represents the color’s “true” value rather than a dark/light variant.

Add Acme, Inc. colors to acme-theme.js like so:

export const acme = {
 global: {
   colors: {
     ruby: {
       dark: "#d4111e",
       light: "#f58990"
     },
     "ruby!": "#EF3F4C",
     gold: {
       dark: "#df9007",
       light: "#e7b86b"
     },
     "gold!": "#F9B644",
     amethyst: {
       dark: "#9B59B6",
       light: "#C39BD3"
     },
     "amethyst!": "#AF7AC5",
     "grey-1": "#ECE9E3",
     "grey-2": "#CECCC6",
     "grey-3": "#737069",
     "grey-4": "#52504C", 
   }
 }
};

Map Colors to Grommet Namespaces and Components

Now that the colors are defined, it’s time to apply them. For the purposes of this tutorial, I will only map the colors to a handful of theme properties. This will demonstrate the process of implementation, but it is certainly not exhaustive. For the curious, inspecting Grommet’s base theme is a great place to take inventory of the many possibilities to fully customize your own theme.

Modify acme-theme.js by mapping the colors to background, brand, control, and anchor properties:

export const acme = {
 global: {
   colors: {
     /* BEGIN: Color Palette Definition */
     ruby: {
       dark: "#d4111e",
       light: "#f58990"
     },
     "ruby!": "#EF3F4C",
     gold: {
       dark: "#df9007",
       light: "#e7b86b"
     },
     "gold!": "#F9B644",
     amethyst: {
       dark: "#9B59B6",
       light: "#C39BD3"
     },
     "amethyst!": "#AF7AC5",
     "grey-1": "#ECE9E3",
     "grey-2": "#CECCC6",
     "grey-3": "#737069",
     "grey-4": "#52504C",
     /* END: Color Palette Definition */
     /* BEGIN: Mapping Colors to Grommet Namespaces */
     background: {
       dark: "grey-4",
       light: "grey-1"
     },
     "background-back": {
       dark: "grey-4",
       light: "grey-1"
     },
     "background-front": {
       dark: "grey-3",
       light: "grey-2"
     },
     brand: "ruby!",
     control: {
       dark: "brand",
       light: "brand"
     },
     input: {
       background: "blue"
     },
     text: {
       dark: "grey-1",
       light: "grey-3"
     }
   },
   focus: {
     border: {
       color: "gold"
     }
   }
   /* END: Mapping Colors to Grommet Namespaces */
 },
 /* BEGIN: Mapping Colors to Components */
 anchor: {
   color: {
     dark: "gold",
     light: "amethyst!"
   }
 }
 /* END: Mapping Colors to Components */
};

Merging a Custom Theme with an Existing Theme

In App.js, add the following imports:

  • import { deepMerge } from “grommet/utils”;
    • A function allowing an existing theme to be customized or extended
  • import { acme } from “./acme-theme”;
    • Our custom theme file
  • import { DemoSection } from “./DemoSection”;
    • A section of sample components to see how theme customizations are applied

Then, add the line const theme = deepMerge(grommet, acme). The imported deepMerge function incorporates the acme specifications into the grommet theme, resulting in a new custom theme.

import React from "react";
import { Grommet, grommet, Anchor, Box, Button, Heading, Paragraph } from "grommet";
import { deepMerge } from "grommet/utils";

import { acme } from "./acme-theme";
import { DemoSection } from "./DemoSection";

const theme = deepMerge(grommet, acme);

Finally, swap out the grommet theme with the newly created theme.

  <Grommet full theme={theme} themeMode={darkMode ? "dark" : "light"}>

That concludes this tutorial. Your final code and resulting app should resemble this Codesandbox. I hope you have enjoyed this three-part tutorial.

As review, here’s how the app was modified:

  • Created a custom theme file.
  • Defined the color palette and its namespaces.
  • Mapped the color namespaces to Grommet namespaces and component definitions.
  • Finally, merged the theme customizations with Grommet’s theme.

Next Steps for Exploration

Now that you have seen how easy it is to apply a theme to Grommet, set and toggle the theme’s light/dark modes, and even start applying custom colors to your own theme, here are some great next steps you can take:

  • Check out Grommet’s Theme Designer (Beta) and other Grommet Resources.
  • Explore Grommet’s other theme properties which can be customized.
  • Create and apply your own theme to your own project, then share it on Grommet’s #i-made-this Slack channel for community members to enjoy.

Related

Shimrit Yacobi

Contributors enhance Grommet during Hacktoberfest

Oct 28, 2019
Matt Glissmann

Dark Mode Theming in Grommet - Part 2: Adding dark and light theme modes

Dec 15, 2023
Matt Glissmann

Dark Mode Theming in Grommet - Part 1: How to set up and apply a theme

Dec 15, 2023
Pramod Sareddy

How to Register a Grommet OSB Broker in a Kubernetes Service Catalog

Aug 21, 2019
Dale Rensing

Meet Eric Soderberg and Shimrit Yacobi - HPE DEV Team Members working on Grommet

Feb 7, 2020
Dale Rensing

Meet Open Source Grommet Expert, Shimrit Yacobi

Sep 22, 2022
Shimi Yacobi

New Grommet release offers new components and improves accessibility

Oct 8, 2020
Pramod Sareddy

Use Grommet Face Detection and Microsoft Azure Cognitive Services to identify people in pictures

Nov 1, 2019

HPE Developer Newsletter

Stay in the loop.

Sign up for the HPE Developer Newsletter or visit the Newsletter Archive to see past content.

By clicking on “Subscribe Now”, I agree to HPE sending me personalized email communication about HPE and select HPE-Partner products, services, offers and events. I understand that my email address will be used in accordance with HPE Privacy Statement. You may unsubscribe from receiving HPE and HPE-Partner news and offers at any time by clicking on the Unsubscribe button at the bottom of the newsletter.

For more information on how HPE manages, uses, and protects your personal data please refer to HPE Privacy Statement.