Design system

Using Stitches to style your projects

Via the WPDS UI Kit

Stitches

The Washington Post Design System utilizes the css-in-js library, Stitches, to optimize app performance and dev experience. For more context about why we use Stitches, check out this post by the WPDS team.


Stitches functions

Stitches functions make creating and styling components easy. Below, we’ll dive into the functions most useful to a user of our UI Kit, but check out Stitches’ other functions if you’re curious.

Styled

The styled function is used to simply create React components with styles. The arguments to the function are:

  1. either an HTML element or a react component
  2. styles

Component variants may also be specified. For example:

import { styled, css } from '@washingtonpost/wpds-ui-kit'

// create a new component, 'FancyButton', which modifies a 'button' element
const FancyButton = styled('button', {
	// base styles

	variants: {
		variant: {
			fancier: {
				// fancier styles
			},
			fanciest : {
				// fanciest styles
			},
		},
	},
});

// Use it
<FancyButton>I'm fancy!</FancyButton>
<FancyButton variant="fancier">I am fancier!</FancyButton>

CSS

The css function can be used to create reusable styles through the application of a class name or used inline to style individual elements. Here’s an example of inline use, utilizing the already defined FancyButton from before:

<FancyButton css={{ //base styles, optional variants }}>I'm fancy!</FancyButton>

And below demonstrates the application of css through the classname property:

const newButton = css({
  // base styles
});

// Use it
<div className={newButton()}>I'm new!</div>;

**note: style property names use camel case in these functions (example: z-index becomes zIndex)

Keyframes

Another function available in Stitches is the keyframes function. Using the keyframe animation technique, Stitches allows the creation of global CSS keyframe rules, which lets transitions be easily reused across code. Below is an example of a simple fading-out animation:

import { keyframes } from '@washingtonpost/wpds-ui-kit'

const fadeOut = keyframes({
	from: { opacity: 1 },
	to: { opacity: 0 },
});

// Use it
const fadingInButton = styled("button", {
	'&hover': {
		animation: `${fadeOut} 200ms ease-out`,
	}
)};

Theme object and tokens

The theme object contains useful token data that can be applied when styling an element. WPDS specifies its own tokens for many attributes, which can be explored throughout the foundations section of our documentation. Tokens can be accessed in code by using the theme object, which is is preferred over using the $ reference symbol because it provides additional checks. For more information about using our theme tokens, check out this tutorial.

The const WPDS is pre-defined in the UI Kit's stitches.config.ts file.

const WPDS = stitches.createStitches({
  prefix,
  theme: {
    colors: {
      ...tokens.light,
      ...tokens.staticColors,
      ...tokens.defaultTheme,
    },
    sizes: tokens.sizes,
    ...
  },
  media: { ... },
  utils: { ... },
});

// Use it
const BestButton = styled('button', {
	// use the size token $200, which is equivalent to 2rem or 32px
	marginTop: theme.space["200"],
	// use the color token $primary, which is equivalent to rgba(17, 17, 17, 1)
	// color tokens change automatically when a color theme is applied
	color: theme.colors.primary,
});

Breakpoints

Stitches is also capable of defining breakpoints, which are reusable media queries useful for responsive styling. The WPDS UI Kit supports a variety of size breakpoints and custom themes, which can be explored in the kit's stitches.config.ts file. The button in the example below would be uniquely styled when the viewport is smaller than 768px, or sm.

const WPDS = stitches.createStitches({
  prefix,
  theme: { ... },
  media: {
    sm: "(max-width: 767px)",
    md: "(min-width: 768px) and (max-width: 899px)",
    lg: "(min-width: 900px) and (max-width: 1023px)",
		...
  },
  utils: { ... },
});

// Use it
const VariableButton = styled('button', {
	// Base styles
	"@sm" {
		// small-screen styles
	},
});

Note: the "@dark" and "@light" media queries are responsive only to OS preferences, so styles specified with these will not affect elements based on the theme toggled in the application. To style an element based on local theme, consider stying based on the parent html element using the syntax: [".<className> &"]. For example:

// Adding opacity to an image when local dark mode is enabled.
const StyledImage = styled(Image, {
  paddingRight: "$075",
  [".wpds-dark &"]: { opacity: "0.9" },
});

Utils

Utils allow the creation of custom shortcuts to write certain styling properties. For example, the WPDS ui kit has defined utils px and py, which affect horizontal and vertical padding, respectively. px could then be used in place of padding-left and padding-right when styling elements. Check out the other utils WPDS supports defined in the config file.

const WPDS = stitches.createStitches({
  prefix,
  theme: { ... },
  media: { ... },
  utils: {
    px: (value: Stitches.PropertyValue<"padding">) => ({
      paddingLeft: value,
      paddingRight: value,
    }),
    py: (value: Stitches.PropertyValue<"padding">) => ({
      paddingTop: value,
      paddingBottom: value,
    }),
		...
  },
});

// Use it
<p css={{ px: "$075", py: "$100" }}>Paragraph with padding</p>

Global styles

Another feature of the UI Kit that provides greater consistency is globalStyles. In the globalStyles definition, default styles for certain properties are specified by using Stitches’ globalCSS function. A darkModeGlobalStyles modification is also specified, which alters default color styles in dark mode.

Dark theme

The WPDS UI Kit currently supports a light and a dark theme. Using the Stitches function createTheme, tokens specified in the theme object can be overwritten to create custom themes. In the case of our UI Kit, the dark theme is employed when the breakpoint dark is toggled.


Contributing

If your team would benefit from an additional util, breakpoint, or something else, please reach out to the WPDS team!