Building Design System UI kits for large frontend applications

Design systems have become more crucial for building large scale frontend applications. They are used to build reusable components which help us to build, scale and maintain the frontend applications.

Building complex frontend architecture requires starting with small foundation blocks. This foundation helps us build the application’s castle. Reusable components are just like Lego blocks which can be used to build various products.

Photo Credits: Steffi Timm
What is a Design System ?

A design system is a complete guide to the UI components shared between multiple projects. It is also the source of truth for an organization’s shared UI components. It focuses on core workflows that promote adoption and simplify maintenance.

Storybook Design System Workflow

In this article we will be discussing how we can build reusable components by using this workflow.

Pre-requisite: Node (version 14 or above).

Let’s create a simple React application using the below command.

npx create-react-app starter-design-systems --template typescript

This will create a React starter project with app name starter-design-system. Next open this project in your IDE (I’m using Visual Studio Code).

Now let’s install the following packages to get started with the design system. Go to the terminal for the above project. The below commands should install the necessary packages (Installation may take some time).

#Install the React bootstrap frontend framework
npm install react-bootstrap bootstrap
#Installs the testing packages
npm install --save-dev react-test-renderer @types/react-test-renderer
#Installs and initializes the storybook
npx storybook init

If your current node version is below 14.17, you will need an additional package to run the jest commands.

#Installs the typed definitions for react-test-renderer
npm i --save-dev jest-watch-typeahead

Initializing the storybook bootstraps the related folders and files into the project. It creates a .storybook folder in the root of the project and a stories folder in src/ , which will contain all the component’s story files.

Also import the bootstrap.css file inside the src/index.tsx file and .storybook/preview.js file. This will add all the bootstrap css and styles to the project and storybook stories.

import ‘bootstrap/dist/css/bootstrap.css’;
Index.tsx and preview.js file with import bootstrap css

Next let’s run the storybook

npm run storybook

This will open the storybook page in Google Chrome which shows the list of reusable components. By default, Storybook gives three new components: Button, Header and Page. These components can be removed if not needed.

Storybook in Browser

Let’s create an Alert component which can give an alert message and also change the color based on the type of alert.

Create a components folder in the src/ folder. Inside this folder create an alert folder. Inside this folder create a file alert.tsx

src -> components -> alert -> alert.tsx
File structure for components

Copy the following code for the alert component in alert.tsx.

import { Alert as ReactAlert } from ‘react-bootstrap’
import { Variant } from ‘react-bootstrap/esm/types’;
interface Props {
variant?: Variant;
message?: string;
}
const Alert = ({ variant, message } : Props) => {
return (<ReactAlert variant={variant}> {message} </ReactAlert>)
}
Alert.defaultProps = {
variant: ‘success’,
message: ‘This is an alert message’
}
export default Alert;

Now let’s create a story for this component in order to view the component in the storybook interface. Create a file alert.stories.tsx inside the src/stories folder with the following code.

import { ComponentStory, ComponentMeta } from ‘@storybook/react’;
import Alert from ‘…/components/alert/alert’;
enum VariantType {
Primary = “primary”,
Secondary = “secondary”,
Danger = “danger”,
Success = “success”,
}
export default {
title: ‘Example/Alert’,
component: Alert,
argTypes: {
variant: {
control: { type: “select”, options: VariantType },
description: “Type of alert”,
defaultValue:“success”,
},
message: {
control: ‘text’,
description: ‘Enter the alert message’,
defaultValue: ‘This is an alert message’
}}} as ComponentMeta<typeof Alert>;
const Template: ComponentStory<typeof Alert> = ({variant, message}) => <Alert variant={variant} message={message} />;
export const Default = Template.bind({});
Default.args = {
variant: “success”
}

You can read more about storybook configuration here.

If you save these files and refresh the running storybook interface in the browser you should be seeing an Alert component in the component lists. If you don’t see your new component in the Storybook, then stop and run the storybook command.

Storybook canvas interface with new component

This will also add the documentation for the component in Docs tab which can be used as a reference while using the component in the application.

Storybook Docs tab

Storybook UI can help us isolate the building of components in parallel with the Application UI. A large frontend application may have many different types of reusable components.

Sample Storybook components list

We can also create stories for these components in the Storybook UI by creating .stories.mdx inside the src/stories/ folder. This will also add the Markdown syntax along with .jsx syntax. You can find more info about the .mdx documentation here.

Next we will need to create snapshot tests. Creating a snapshot of the component can make sure it does not change unexpectedly.

Create a new file alert.spec.tsx inside the alert component folder and add the following code which will create a snapshot of the alert component.

import renderer from ‘react-test-renderer’;
import Alert from ‘…/alert/alert’;
it(‘renders correctly’, () => {
const tree = renderer
.create(<Alert variant=‘success’ message=‘This is an alert message’/>)
.toJSON();
expect(tree).toMatchSnapshot();
});
src->components->alert->alert.spec.tsx

Run npm run test to generate a snapshot for the alert component. This will create a snapshots folder in which the .snap file is generated.

File structure for the snapshots and tests

You can also add other testcases to this .spec file based on the component’s functionality test coverage.

Now this component can be used anywhere else in the application. Any change to this component will fail the npm test. These snapshots must be updated based on the changes so that any unexpected changes can be recognized early.

Final Thoughts

Creating a complex frontend application requires a lot of planning, design and development. Building a design system in the initial phases of software development lifecycle can help us to reach the deliverables with much ease and precision.

References:

  1. https://storybook.js.org/
  2. https://jestjs.io/docs/tutorial-react

Building Design System UI kits for large frontend applications was originally published in Walmart Global Tech Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.

Article Link: Building Design System UI kits for large frontend applications | by Sai Kiran | Walmart Global Tech Blog | Medium