Search
author logo
Matt Glissmann

Dark Mode Theming in Grommet: Theme color customization

October 28, 2020

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, Anchor, Box, Button, Heading, Paragraph } from "grommet";
import { grommet } 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 Tools.
  • 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

author logo
Joel Baxter & Kartik Mathur & Don Wake

Building Dynamic Machine Learning Pipelines with KubeDirector

Aug 14, 2020
author logo
Nicolas Perez

Apache Spark as a Distributed SQL Engine

Jan 7, 2021
author logo
Nicolas Perez

Apache Spark Packages, from XML to JSON

Dec 11, 2020
author logo
Carol McDonald

Apache Spark Machine Learning Tutorial

Nov 25, 2020
author logo
Dale Rensing

App DEV and the HPE Container Platform

Apr 9, 2020
author logo
Suzy Visvanathan

Best Practices for Migrating Your Apps to Containers and Kubernetes

Nov 25, 2020
author logo
Carol McDonald

Big Data Opportunities for Telecommunications

Nov 5, 2020
author logo
Didier Lalli

Calling all developers… Make your voices heard!

Dec 8, 2020

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.