React: ThemeProvider Styling Solutions

author-avatar

Introduction

So there you are, it’s been hours since you started searching the web looking for parts to customize your car, to make it stand out in the street, to make it louder and faster, perhaps you want a better stance or maybe some flashy wheels. What you want is to customize it, to ride in style.

Just like a car, the web has different parts (components) that I have to modify so it stands out from the rest. 

The choices you make, the parts you select, and the approach you take to customize a car are, believe it or not, similar to the ones you make for an app. Bad choices, and the car will end up worse than its stock form, so choose your customization approach carefully. For the car you will need patience, research, and money (tons of it). For the app, however, you can try a ThemeProvider from Material UI.

What’s a Theme?

A theme specifies characteristics of components such as colors, fonts, level of shadow, appropriate opacity of ink elements, etc.

A theme allows you to customize all design aspects of your app in order to meet your specific needs. – See? like the car.

Think of the most common example, nowadays apps have a dark and light mode to choose from, and that’s a theme. Different libraries provide mechanisms to accomplish this feat, usually called ThemeProvider, since the app I’m working on uses Material-UI, I’ll walk you through it, but remember the idea is the same regarding the library you use.

ThemeProvider

To customize your theme you can use a ThemeProvider which is a feature that uses the React context API to pass down the theme to components in the react tree.

The first thing you want to do is, Not coding until you have a design system that reflects the different states (style-wise) a component can have. You need to know that beforehand or you will accomplish nothing, the whole point of this is to define the theme only once.

So, once you have that you can go ahead and write some code. The first thing will be to create a theme file.

And tell the theme what variables we are customizing. In this case, we are building a tooltip.

import { createMuiTheme } from "@material-ui/core/styles";
import { COLORS } from "colors/colors";
const materialTheme = createMuiTheme({
  typography: {
    fontFamily: ["Quicksand", "sans-serif", "Arial"].join(",")
  },
  palette: {
    primary: { main: "#212C52" }
  },
  overrides: {
    MuiTooltip: {
      tooltip: {
        backgroundColor: COLORS.darkblue100,
        maxWidth: 164,
        fontSize: 10,
        padding: 10
      },
      arrow: {
        color: COLORS.darkblue100
      }
    }
  }
});
export default materialTheme;

Next, we wrap our app with the ThemeProvider at the highest level possible so all the components can benefit from it. 

const App = () => {
  return (
    <Router>
      <Provider store={reduxStore}>
        <ThemeProvider theme={materialTheme}>
          <AppLayout />
        </ThemeProvider>
      </Provider>
    </Router>
  );
};

And now to the tooltip component. 

import React from "react";
import { Tooltip as MaterialTooltip } from "@material-ui/core";
import { Div } from "./StyledComponents";
type TooltipPlacement =
  | "bottom-end"
  | "bottom-start"
  | "bottom"
  | "left-end"
  | "left-start"
  | "left"
  | "right-end"
  | "right-start"
  | "right"
  | "top-end"
  | "top-start"
  | "top";
type TooltipProps = {
  title: string;
  arrow?: boolean;
  placement?: TooltipPlacement;
  width?: number;
};
const Tooltip: React.FC<TooltipProps> = ({
  title,
  arrow = true,
  placement = "top",
  children
}) => {
  return (
    <MaterialTooltip title={title} arrow={arrow} placement={placement}>
      <Div>{children}</Div>
    </MaterialTooltip>
  );
};
export default Tooltip;

Notice how we are not adding any className prop or using any styled component feature, we are just implementing the tooltip but no styling is involved in this file.  

What’s the idea here? It’s to simplify and minimize the amount of code we need to write to style a component. What we want is to improve the consistency of styles applied to the app.

Let us look at how this bunch of code looks like in the browser:

The tooltip will look the same across the entire application, if we want to change its background because we are now in Dark Mode we could simply change the theme without any other modifications to the component, we don’t need to add logic in it about it, the theme will handle it.

Less code, cleaner code, more style!