Skip to main content
Design system

React Guide

We're going to walk through how to build a feature for the website with our React UI Kit.


We're going to build a "save to reading list" feature for the website.

Pre-requisites

We will need a few things to get started. First, we need to install the React UI Kit. This guide assumes you have a Next.js project set up.

npm install @stitches/react
npm install @washingtonpost/wpds-ui-kit

Let's configure the project to support Server Side Rendering. This is a requirement for the React UI Kit in Next.js. We are following Stitches guide on how to do this. Seen here.. You need to call ‘getCssText()’ in the document head to prevent FOUC during SSR.

import React from "react";
import NextDocument, { Html, Head, Main, NextScript } from "next/document";
import { getCssText } from "@washingtonpost/wpds-ui-kit";

export default class Document extends NextDocument {
  static async getInitialProps(ctx) {
    const initialProps = await NextDocument.getInitialProps(ctx);
    return { ...initialProps };
  }

  render() {
    return (
      <Html lang="en">
        <Head>
          <style
            id="stitches"
            dangerouslySetInnerHTML={{ __html: getCssText() }}
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

Create a new component file in your "components" directory with the following code:

import { styled, Icon, theme } from "@washingtonpost/wpds-ui-kit";
import Add from "@washingtonpost/wpds-assets/asset/add";

export const SaveToList = () => {
  return (
    <Icon size="$200" label="Save to reading list" fill={theme.colors.primary}>
      <Add />
    </Icon>
  );
};

Let's walk through each line of code. We will be using the styled function to create a styled component. We will also be using the theme object to get the current theme. We will also be using the Icon component to create an accessible icon.

import { styled, Icon, theme } from "@washingtonpost/wpds-ui-kit";

The styled function takes a component and returns a styled component. It uses Stitches under the hood.

The theme object lets us use our Theme tokens with type safety. We can also use the cool "interpolation" syntax to get the current theme. Like so $primary will return the current primary color.

The Icon component clones the SVG React element and adds accessibility attributes. We can use the label prop to set the aria-label attribute. We can also use the size prop to set the width and height attributes.

We will use a new asset from our Assets Manager.

<Add />

Let's create a new button component with the following code. We will use the Icon asset and apply the fill prop to set the color.

import { styled, Icon, theme } from "@washingtonpost/wpds-ui-kit";
import Add from "@washingtonpost/wpds-assets/asset/add";

const Button = styled("button", {
  color: theme.colors.onPrimary,
  backgroundColor: theme.colors.primary,
});

export const SaveToList = () => {
  return (
    <Button>
      Save to reading list
      <Icon size="$200" fill={theme.colors.onPrimary}>
        <Add />
      </Icon>
    </Button>
  );
};
import { styled, Icon, theme } from "@washingtonpost/wpds-ui-kit";
import Add from "@washingtonpost/wpds-assets/asset/add";

const Button = styled("button", {
  // remove all browser styles
  appearance: "none",
  border: "none",
  // add press effect
  "&:active": {
    transform: "scale(0.95)",
  },
  // give it some color
  color: theme.colors.onPrimary,
  backgroundColor: theme.colors.primary,
  // remove default spacing
  margin: 0,
  // add some padding
  padding: theme.space["050"],
  // add rounded corners
  borderRadius: theme.radii.round,
  // add a uniform box shadow to create a 'border' effect
  boxShadow: "0 0 0 1px currentColor",
  // remove extra space drawn when line height and font size are set
  lineHeight: 0,
  fontSize: 0,
  // add a pointer
  cursor: "pointer",
});

const SaveToList = () => {
  return (
    <Button>
      <Icon size="$200" fill={theme.colors.onPrimary}>
        <Add />
      </Icon>
    </Button>
  );
};

export default function Example() {
  return <SaveToList />;
}

Further Reading

Further reading:

Further watching: