White labeling colors in embedded applications
Tags: react, javascript, css, frontend
Published: 2023-10-07 12:52:54

When an application is embedded there is often a need to customize it to match someone else's product. It involves setting a custom color palette, font attributes, logo images, and more. The process of applying of another brand is called white labeling.

In this article, we will focus on the approach of managing colors on the frontend to make them customizable by a third-party application.

## Identifying derived colors

The first step is to identify which colors can be computed based on other colors. The following questions might help:
- Are some colors close to each other? 
- Is one color lighter/darker than another?
- Was there an intent to match certain colors in the app?

In the following example `color-focus` is used for the focus ring for inputs. It looks like a lighter version of `color-blue`, and the designers have confirmed that they had an intent to match this color. After trying different parameters  `lighten("blue", 0.464)` gave the value of the "focus" color.

```css
:root {
  --color-blue: #519ee4;
  --color-focus: #cbe3f8;
}
```

When colors can have arbitrary values it is usually a good idea to rename them to match the original intent rather than the default value. For instance, if in your application `color-blue` is the main brand color it makes sense to rename it to `color-brand`:

```css
:root {
  --color-brand: #519ee4;
}
```

## Passing derived colors

It is currently not possible to compute dynamic color values purely in CSS, mostly because there are no color transformation functions available. We can use JS to set values of base and derived colors, and then use them in other stylesheets: With the following color palette:

```javascript
const baseColors = {
  brand: "#519ee4",
};

const derivedColors = {
 focus: lighten(baseColors.brand, 0.464),
};

const colors = { 
  ...baseColors,
  ...derivedColors,
}; 
```

Set CSS color variables with vanilla JS:

```javascript
const root = document.querySelector(':root');
Object.entries(colors).forEach(([name, value]) => {
  root.style.setProperty(`--color-${name}`, value);
});
```

Set CSS color variables with `emotion`:

```javascript
import { css, Global } from "@emotion/react";

function GlobalStyles() {
  const styles = css`
    :root {
      ${Object.entries(colors).map(([name, value]) => 
        `--color-${name}: "${value}";`
      )}
    }
  `;

  return <Global styles={styles} />;
}

function App() {
  <>
    <GlobalStyles />
    {/* your app */}
  </>
}
```

When CSS color variables are set on the root element you can continue using them in the same way you did with static CSS variables:

```css
.button:focus-visible: {
  outline: 2px solid var(--color-focus);
}
```

## Desaturated colors

There are certain colors in the app that cannot be configured in an arbitrary way. For instance, people usually expect green  success messages and red error messages. We could use desaturated green and red colors, which are closer to greyscale and appear less vibrant than the original color.

```css
:root {
  --color-success: #85BC4D; // desaturated green color 
}
``` 

These colors work well with most color palettes and usually are not configured by an external application.