Building a design system with Grommet and Storybook
Tags: featuredposts, react, webdev
Published: 2019-09-12 14:45:51

---
title: Building a design system with Grommet and Storybook
published: true
tags: Featured Posts,react,webdev
canonical_url: https://blog.logrocket.com/building-design-system-grommet-storybook/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/wxa1p5gt4n9k4a0tvtg9.jpg
---
**Written by [Emmanuel Yusufu](https://blog.logrocket.com/author/emmanuelyusufu/)**✏️

## Introduction

We’ve all heard the buzzword “design system” thrown up and down. But how do we make sense of it, and more importantly, how do we build one for ourselves? This post will guide you through creating a design system using React, Grommet, and Storybook.

## What exactly is a design system?

A design system consists of a design language, a component library, and a documentation/style guide website where the first two live.

As detailed in [this talk by Emma Wedekind](https://www.youtube.com/watch?v=ropAuzI7MtA&t=24s), when developers talk about design systems, they mostly refer to the component library; when designers do, they refer to the design language. Project managers are most likely concerned with the documentation/style guide website where everything lives.

The following expatiates on the purpose of these three pieces:

- **Design language:** This helps shape our products into a representation of our brand. It includes color (for emotion), type scale, accessibility, and motion (for personality).
- **Component library:** These are reusable code components that serve as the building blocks of our application. They also give expression to the design language. These include buttons, input fields, etc. If you aren’t building yours from scratch, you could customize a popular library such as Grommet to your project needs.
- **Documentation/style guide website:** This is the site where you document everything about the design language and component library. This creates consistency by allowing all your team members to access it for use.

Design systems generally provide building blocks with which we construct our applications. It leads to consistent user experience across a company’s suite of products as they become more complex and its teams grow in size.

All major software companies have [their own design system](https://enonic.com/blog/top-12-design-systems). Some examples of popular design systems are Shopify’s [Polaris](https://polaris.shopify.com/), Google’s [Material Design](https://material.io/design/), and Trello’s [Nachos](https://blog.trello.com/introducing-nachos-a-tasty-new-design-system-for-trello).

So, how do you build one for your own brand? You first need to have the three pieces of a design system in place.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## Grommet

[Grommet](https://v2.grommet.io/) is a React component library that provides responsive and accessible mobile-first code components you can easily use for your projects.

Of particular note is the fact that Grommet provides powerful theming tools that let you tailor the component library to align with your color, type, component interaction, and layout needs. This addresses the design language piece we discussed earlier.

## Storybook

Storybook is an open source tool that allows you to document and explore your code’s components. It works with React, Vue, and Angular, and it also enables you to work on your components in isolation and test them in different states.

Most importantly, Storybook enables automatic generation of a customizable style guide site.

## Installation

To get started, let’s scaffold a blank React app.

```jsx
npx create-react-app my-app
cd grommet-storybook-react-app
```

Open the project in your code editor. The next step is to install Grommet:

```jsx
npm install grommet styled-components --save
```

Also install Storybook:

```jsx
npx -p @storybook/cli sb init
```

Recall that Storybook can be used for React, Vue, and Angular. The above command will detect which framework we are using and install the appropriate Storybook version. In our case, the React version `@storybook/react` will be installed.

After the installation, run the app:

```jsx
npm run storybook
```

The following screen will be displayed in the browser:

![Storybook's Default Welcome Component](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2019/09/storybook-welcome-component-browser.png?resize=730%2C400&ssl=1)

As you can see in the component explorer, Storybook provided two components out of the box for demo purposes. These are the `Welcome` and `Button` components.

If we look into our project folder, we’ll notice `.storybook` and `stories` folders have been added after the installation.

![Stories Folder In Our Project Directory](https://i1.wp.com/blog.logrocket.com/wp-content/uploads/2019/09/stories-folder.png?resize=730%2C377&ssl=1)

Visit the `stories/index.js` folder to see the demo components. Observe and remove or comment out the portion below; we will be building our own welcome and button components.

```jsx
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);

storiesOf('Button', module)
  .add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>)
  .add('with some emoji', () => (
    <Button onClick={action('clicked')}>
      <span role="img" aria-label="so cool">
        😀 😎 👍 💯
      </span>
    </Button>
  ));
```

This is what should be left:

```jsx
import React from 'react';

import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';
```

![Default Storybook Components Removed](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2019/09/storybook-components-removed-browser.png?resize=730%2C422&ssl=1)

## Creating our components

Now, onto the main thing: we’ll start by building welcome and button components just like we saw earlier.

One of the qualities of any good documentation is that it has a welcome note that helps developers get started. This usually provides a setup or installation guide. Let’s pretend we were building a design system for your company. We could use the `welcome` component as our welcome note. That means it will just be filled with plaintext.

### The `Welcome` component

Create a `components` folder inside the `src` folder, then create a `Welcome.js` file inside `components`. Place the following code into the file:

```jsx
import React from 'react';
import { Heading, Paragraph, Box } from 'grommet';

class Welcome extends React.Component {

  render() {
    return (
      <Box direction="column" pad="medium">

        <Heading margin="none" level="3">Chapter 1</Heading>
        <Paragraph margin="none">
          Lorem ipsum dolor sit amet,
          consectetur adipiscing elit,
          sed do eiusmod tempor incididunt ut
          labore et dolore magna aliqua.
        </Paragraph>
        <Paragraph margin="none">
          Lorem ipsum dolor sit amet,
          consectetur adipiscing elit,
          sed do eiusmod tempor incididunt ut
          labore et dolore magna aliqua.
        </Paragraph>

      </Box>
    );
  }

}

export default Welcome;
```

In the above code, we imported `Heading` and `Paragraph`, which are type components from Grommet. We also imported `Box`, which is a container to lay out our content. Everything is inside a `Welcome` component, which we have set up for export.

Inside the `stories` folder, go to `index.js` and import the `Welcome` component.

```jsx
import Welcome from '../components/Welcome';
```

Also add the following to `index.js`:

```jsx
storiesOf('Welcome', module).add('getting started', () => <Welcome />);
```

In Storybook, a story refers to a component and several possible states of it — for example, a button in different states.

In the code above, the `storiesOf()` function helps us name a particular story in the component explorer interface, and the `.add()` function sets up a dropdown, which, when released, presents different states of the component. This will be clearer when we create our next component.

![Custom Welcome Component In Storybook](https://i1.wp.com/blog.logrocket.com/wp-content/uploads/2019/09/storybook-custom-welcome-component.png?resize=730%2C375&ssl=1)

### The `Button` component

Buttons are used a lot in interfaces. They have great impact on products and are a great place to start when creating a design system.

To create the `Button` component, create a `Button.js` file inside the `components` folder. Paste the following code in:

```jsx
import React from 'react';
import { Button as GrommetBtn } from 'grommet';


class Button extends React.Component {
  render() {
    return (
      <GrommetBtn label="default" />
    );
  }
}

export default Button;
```

Notice that because I want to create our own component called `Button`, I had to rename Grommet’s default button to `GrommetBtn` to prevent name clashing.

Now import the `Button` component in `index.js`:

```jsx
import Button from '../components/Button';
```

Add the button story to the same file:

```jsx
storiesOf('Button', module).add('basic', () => <Button />);
```

This will render out as shown:

![Custom Primary Button In Storybook](https://i1.wp.com/blog.logrocket.com/wp-content/uploads/2019/09/storybook-custom-default-button.png?resize=730%2C433&ssl=1)

As expected in any design system, we should be able to reuse a component like our button in many situations. This is usually done by passing custom props to the component.

Whatever props are passed will affect the way a component is rendered. Fortunately, Grommet comes with enough props for each component to fill your needs.

To ensure our button component receives any props passed to it from `index.js`, go to `Button.js` and add an expression between curly braces.

```jsx
<GrommetBtn label={this.props.label} {...this.props} />
```

Now let’s create and document different variations of our button. Go to the button story and make the following changes:

```jsx
storiesOf('Button', module)
  .add('primary', () => <Button primary label="primary" />)
  .add('secondary', () => <Button primary={false} label="secondary" />)
  .add('plain', () => <Button plain label="plain" />)
  .add('Disabled', () => <Button disabled label="Disabled" />);
```

When we run the code, we should see the following screen:

![Custom Secondary Button In Storybook](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2019/09/storybook-custom-secondary-button.png?resize=730%2C521&ssl=1)

Grommet buttons have lots of useful props, such as `accessibilityTitle`, `active`, `icon`, `plain`, `target`, `size`, `onClick`, `href`, `id`, `label`, `type`, etc. Feel free to [check them all out here](https://storybook.grommet.io/?path=/story/button--basic).

It is worth mentioning that Storybook can be supercharged [with add-ons, which you can see here](https://storybook.js.org/addons/). Add-ons are extra features that can be appended to Storybook to make it more useful and add advanced functionality.

Examples are [the Source add-on](https://github.com/storybookjs/storybook/tree/master/addons/storysource) (which lets you view the component’s source code to copy and paste), [the notes add-on](https://github.com/storybookjs/storybook/tree/master/addons/notes) (for documenting component usage in markdown), and the [background add-on](https://github.com/storybookjs/storybook/tree/master/addons/backgrounds) for storybook customization.

## Customizing the Grommet theme

We’ll now take a look at three ways you can customize your Grommet theme.

1. Grommet components have a [top-level wrapper container](https://v2.grommet.io/grommet) that can be used to style components globally.

```jsx
const customTheme = {
    global: {
       colors: {
       custom: "#cc6633"
       }
    }
};

const Themed = () => (
  <Grommet theme={customTheme}>
    <Box pad="medium">
      <Anchor icon={<Add />} label="Add" color="custom" />
    </Box>
  </Grommet>
);
```

1. Grommet also provides [`ThemeContext.Extend`](https://v2.grommet.io/themecontext?c=DwFQFgpgthDCD2A7ALhAHsgdAUQxRAJgFAAEJAbgIYA2ArhALwDeTJA5tfAEY0BcJrAMbxOAJwDO-VgXiD+AcgDEAM2UBONYMHySAXz17dRAHykSwAELw0JAA6UCDAETVKothCckeggNZtReFpCZxlBLwIAS1EIQWRIpGdAgHcvAHpTMktrOwdnV3dPb0o-AKCQpzCI6Nj4xKcU9NNgNPBoOCRUDBw8QmMgA) to style components locally.

```jsx
<ThemeContext.Extend
  value={{ global: { colors: { doc: '#ff99cc' } } }}
>
  <Box pad="large" background="doc" direction="row" />
  <Box pad="large" background="doc" direction="row" />
</ThemeContext.Extend>
```

1. You can also use styled-components to style components individually.

```jsx
import styled from 'styled-components`;
import { Button } from 'grommet';
const MyStyledButton = styled(Button)`
   font-weight: bold;
   background-color: #BADA55;
`;

const MyComponent = () => (
  <div>
     Press Button <MyStyledButton label="Press Me" />
  </div>
);
```

## Deploying your documentation as a static app

In order to showcase our component library to our whole team, we have to deploy it as a site. You can deploy it to Netlify, GitHub pages, or any static hosting service.

Simply add the following npm script to your `package.json`:

```jsx
{
  "scripts": {
    "build-storybook": "build-storybook -c .storybook -o .out"
  }
}
```

Then run `yarn build-storybook`.

This will build Storybook from the project directory into a static web app and place it inside the `.out` directory. You can now deploy the content in the `.out` directory wherever you want.

To test it locally:

```jsx
npx http-server .out
```

## Conclusion

In this post, we’ve explored the technologies that will enable you to build a design system. We’ve covered how to implement components, customization, documentation, and hosting your design system. Now go build something awesome!
* * *
**Editor's note:** Seeing something wrong with this post? You can find the correct version [here](https://blog.logrocket.com/building-design-system-grommet-storybook/).

## Plug: [LogRocket](https://logrocket.com/signup/), a DVR for web apps
 
![LogRocket Dashboard Free Trial Banner](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png?resize=1200%2C677&ssl=1)
 
[LogRocket](https://logrocket.com/signup/) is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
 
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.
 
[Try it for free](https://logrocket.com/signup/).
* * *
The post [Building a design system with Grommet and Storybook](https://blog.logrocket.com/building-design-system-grommet-storybook/) appeared first on [LogRocket Blog](https://blog.logrocket.com).