DEV Community

Alexey Pavlov
Alexey Pavlov

Posted on • Edited on

2

How to create your own React Components library

Are you curious about how to create your own components library on React + Typescript?

In this set of articles we will go through such aspects as: setup project structure, writing a small component, testing, connecting to storybook, deploying project to GitHub Pages and pushing a package to NPM. Let's start by setting up a project!

Set up

We will use a TSDX library - this tool is something similar to create-react-app, but for creating components library. It allows as to initialize a project immediately with already set up bundler, Rollup with Typescript supporting, testing with Jest, code formatter, Prettier and Storybook.

To start, run this command in your terminal with your library name

npx tsdx create fancy-react-lib
Enter fullscreen mode Exit fullscreen mode

Choose a template react-with-storybook - it is a React package with necessary development dependencies and @types installed, with React Storybook already setup as well

Choose a TSDX template

Now we can open a generated project and browse the structure. The first folder is GitHub workflows. The First of them - main.yml, it runs linting, tests and builds the project. The main goal is to check that the project is building successfully in different operating systems and node versions. Some dependencies require node version 14 and upper, so let's update this part of the file:

    strategy:
      matrix:
        node: ['14.x', '16.x']
        os: [ubuntu-latest, windows-latest, macOS-latest]
Enter fullscreen mode Exit fullscreen mode

The next - size.yml. It uses action size-limit to get a final bundle size and push it to pull request. Also, it rejects a pull request if the size is higher than the limit, that was mentioned in package.json.

  "size-limit": [
    {
      "path": "dist/react-super-library.cjs.production.min.js",
      "limit": "10 KB"
    },
    {
      "path": "dist/react-super-library.esm.js",
      "limit": "10 KB"
    }
  ],
Enter fullscreen mode Exit fullscreen mode

We also have next folders in our project:

  • storybook
  • example (it is a playground, but we will use storybook for these purposes)
  • src (we will place our components here)
  • stories (here will be our stories for storybook)
  • test

In general, this is all that we need to know about the project structure. Now we can init a git repository and push it to GitHub.

It's time to create the first piece of code!

Creating a component

Let's start with the button component.

Create a Button folder in src, then create a Button.tsx file.

Nothing complicated, just standard HTML button and several props: onClick, children (ReactNode - it is a type including React Element, string, number, whatever), isDisabled, variant (to use different styles, let's start with primary and success variants).

import React, { ReactNode } from 'react'
import './Button.css'
export type ButtonProps = {
onClick(): void
children: ReactNode
variant?: 'primary' | 'success'
isDisabled?: boolean
}
export function Button({
children,
onClick,
isDisabled = false,
variant = 'primary',
}: ButtonProps) {
const className = `button button-${variant}`
return (
<button onClick={onClick} disabled={isDisabled} className={className}>
{children}
</button>
)
}
view raw Button.tsx hosted with ❤ by GitHub

Styling

You can use any approach to adding CSS styles, that you like. I will show the easiest way - just add a CSS file for our component. Create a Button.css in src/Button folder and paste styles below

.button {
color: #fff;
padding: 0.5rem 2rem;
border: 0;
border-radius: 0.25rem;
}
.button-primary {
background-color: #4747d0;
}
.button-success {
background-color: #3f8619;
}
view raw Button.css hosted with ❤ by GitHub

We want bundler to provide styles as separate CSS file, for that we need to change Rollup settings bit.

Run this command and follow TSDX customization instructions

yarn add -D postcss rollup-plugin-postcss autoprefixer cssnano

Enter fullscreen mode Exit fullscreen mode

Create a tsdx.config.js file in the root directory and past this code

const postcss = require('rollup-plugin-postcss');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
module.exports = {
rollup(config, options) {
config.plugins.push(
postcss({
plugins: [
autoprefixer(),
cssnano({
preset: 'default',
}),
],
inject: false,
// only write out CSS for the first bundle (avoids pointless extra files):
extract: !!options.writeMeta,
})
);
return config;
},
};
view raw tsdx.config.js hosted with ❤ by GitHub

Storybook

Let's create a story for our button! We already have a default story in the stories folder, so we can create the same one. Create a new file Button.stories.tsx in storybook folder

import React from 'react'
import { Meta, Story } from '@storybook/react'
import { Button, ButtonProps } from '../src/Button/Button'
const meta: Meta = {
title: 'Welcome',
component: Button,
argTypes: {
children: {
control: {
type: 'text',
},
},
},
parameters: {
controls: { expanded: true },
},
}
export default meta
const Template: Story<ButtonProps> = args => <Button {...args} />
// By passing using the Args format for exported stories, you can control the props for a component for reuse in a test
// https://storybook.js.org/docs/react/workflows/unit-testing
export const ButtonStory = Template.bind({})
ButtonStory.args = {
onClick: () => alert('Test'),
children: 'Text'
}

To build storybook locally, run this command:

 yarn storybook
Enter fullscreen mode Exit fullscreen mode

The last but not least, let's export the Button component in src/index.js file - the entry point of our package.

export * from './Button/Button'
Enter fullscreen mode Exit fullscreen mode

Cool! We can check that storybook is working.

Hope it was helpful. The project files you can find also in a GitHub repo.

Top comments (0)

This post blew up on DEV in 2020:

js visualized

🚀⚙️ JavaScript Visualized: the JavaScript Engine

As JavaScript devs, we usually don't have to deal with compilers ourselves. However, it's definitely good to know the basics of the JavaScript engine and see how it handles our human-friendly JS code, and turns it into something machines understand! 🥳

Happy coding!

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay