DEV Community

Cover image for Creating a Gradient Component in React From Design Tokens
Michael Mangialardi
Michael Mangialardi

Posted on

Creating a Gradient Component in React From Design Tokens

If you're not familiar with design tokens, they are simply representations of design specifications in code.

Creating a Gradient Component in React From Design Tokens

By "representations," it is meant that they are key-value pairs that represent design specifications.

Generally speaking, there are two types of design tokens:

  1. "Simple" tokens - Representations of valid values of the design system. These tokens usually cover the colors, typography, spacing, etc. of the design system (i.e. color-red-500, font-bold, etc.).

  2. "Component" tokens - Representations of the design specs for a component/element (i.e. component-button-background-color).

Creating a Gradient Component in React From Design Tokens

With a design tokens pipeline, you can write out design tokens in JSON format, and then translate those "raw"/JSON design tokens into formatted tokens (JavaScript modules, CSS variables, SASS variables, etc.).

With that background in mind, imagine that a design system had "simple" design tokens defining valid colors.

Here's the JSON representation:

{
  "color": {
    "red-50": "#FFC3C2",
    "red-100": "#FFAFAD",
    // ...etc
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, imagine that a design tokens pipeline formats the JSON into the following JavaScript modules:

export colorRed50 = "#FFC3C2";
export colorRed100 = "#FFAFAD";
// ...etc
Enter fullscreen mode Exit fullscreen mode

And, let's say these tokens can be consumed in an application via an npm package:

// SomeComponent.jsx

import * as tokens from "@some/design-system/tokens";

function SomeComponent() {
  const style = { color: tokens.colorRed50 };
  return <div style={style}>Some Component</div>
}
Enter fullscreen mode Exit fullscreen mode

Now, given such a setup, how can we programmatically create gradients when given two color tokens?

Creating a Gradient Component in React From Design Tokens

Here's one way:

// SomeComponent.jsx

import * as tokens from "@some/design-system/tokens";

function SomeComponent() {
  const style = {
    background: `
      linear-gradient(
        45deg,
        ${tokens.colorRed50},
        ${tokens.colorRed100}
      )
    `,
  };
  return <div style={style}>Some Component</div>
}
Enter fullscreen mode Exit fullscreen mode

Ok, but is there a way that we can refactor this?

Well, we could create a helper function that returns the gradient when providing the from and to values:

// get-gradient.js

export default function getGradient(from, to) {
  return `linear-gradient(45deg, ${from}, ${to})`;
}

// SomeComponent.jsx

import * as tokens from "@some/design-system/tokens";

import getGradient from './get-gradient.js';

function SomeComponent() {
  const style = {
    background: getGradient(
      tokens.colorRed50,
      tokens.colorRed100,
    ),
  };
  return <div style={style}>Some Component</div>
}
Enter fullscreen mode Exit fullscreen mode

This refactor doesn't save in lines of code, but it does guarantee that gradients will be created the same so long as they are created through the getGradient helper function.

What if we refactored one step further and allowed the gradient to be applied to any child component via a wrapper component?

// Gradient.jsx

import { Children, cloneElement } from 'react';

function getGradient(from, to) {
  return `linear-gradient(45deg, ${from}, ${to})`;
}

export default function Gradient({ children, from, to }) {
  return Children.map(children, (child) => {
    return cloneElement(child, {
      style: {
        ...child.props.style,
        background: getGradient(from, to),
      },
    });
  });
}

// SomeComponent.jsx

import * as tokens from "@some/design-system/tokens";

import AnotherComponent from './AnotherCompoent.jsx';
import Gradient from './Gradient.jsx';

function SomeComponent() {
  return (
    <Gradient from={tokens.colorRed50} to={tokens.colorRed100}>
      <AnotherComponent />
    </Gradient>
  );
}
Enter fullscreen mode Exit fullscreen mode

By using Children and cloneElement, the Gradient component clones the child element and applies the gradient.

๐ŸŽŠ Awesome! Now, we have a pattern for applying a gradient via a wrapper component in React!

Discussion (0)