Opprette en gradientkomponent i React From Design Tokens

Hvis du ikke er kjent med designtokens, er de ganske enkelt representasjoner av designspesifikasjoner i kode.

Med "representasjoner" menes det at de er nøkkelverdi-par som representerer designspesifikasjoner.

Generelt sett er det to typer designtokens:

  1. «Enkle» tokens – representasjoner av gyldige verdier av designsystemet. Disse symbolene dekker vanligvis fargene, typografien, avstanden osv. til designsystemet (dvs. color-red-500 , font-bold osv.).

  2. «Komponent»-tokens – Representasjoner av designspesifikasjonene for en komponent/element (dvs. component-button-background-color ).

Med en design-tokens-pipeline kan du skrive ut design-tokens i JSON-format, og deretter oversette disse "rå"/JSON-designtokenene til formaterte tokens (JavaScript-moduler, CSS-variabler, SASS-variabler, osv.).

Med den bakgrunnen i tankene, se for deg at et designsystem hadde "enkle" designsymboler som definerer gyldige farger.

Her er JSON-representasjonen:

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

Tenk deg nå at en pipeline for designtokens formaterer JSON til følgende JavaScript-moduler:

export colorRed50 = "#FFC3C2";
export colorRed100 = "#FFAFAD";
// ...etc

Og la oss si at disse tokens kan konsumeres i en applikasjon via en npm-pakke:

// SomeComponent.jsx

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

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

Nå, gitt et slikt oppsett, hvordan kan vi programmatisk lage gradienter når vi får to fargesymboler?

Her er én måte:

// 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>
}

Ok, men er det en måte vi kan refaktorisere dette på?

Vel, vi kan lage en hjelpefunksjon som returnerer gradienten når du gir from og to verdier:

// 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>
}

Denne refaktoren lagrer ikke i kodelinjer, men den garanterer at gradienter vil bli opprettet på samme måte så lenge de opprettes gjennom getGradient hjelpefunksjon.

Hva om vi refaktorerte ett skritt videre og lot gradienten brukes på en hvilken som helst underordnet komponent via en innpakningskomponent?

// 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>
  );
}

Ved å bruke Children og cloneElement , Gradient komponenten kloner det underordnede elementet og bruker gradienten.

🎊 Fantastisk! Nå har vi et mønster for å bruke en gradient via en wrapper-komponent i React!