Build your own React UI library using StoryBook + rollup from scratch

Early introduction

Recently there is a responsible for the front end of the project I split into micro front project, is composed of a base application and a few can run independently, in which each application components used, often need to back and forth between, but not as a single project can easily unified reference, so take a front the interior of the UI component library, Individual submodules can reference components more easily. The library also uses Lerna to allow batch management of NPM package releases, but this is not a necessary option for the purposes of this article.

Whether as a KPI project or their own use, set up a own UI component library believe is the most front end development students direction of one of the most easy to use, but how to start, how to have a relatively good development experience, may is a headache to everybody, so I prepared to offer a build the thinking of the UI component library for all to use, This is the display link, we will finally achieve this effect, and the relevant code has been uploaded to github warehouse, we also hope to get some of your star🌟, issue, suggestion and pull request. It is worth noting that some files don’t from the beginning to the end result, but according to the train of thought to go step by step optimization, so we will not look at a large section of the configuration, not very understand why want to do, do what is good, can have a clearer idea to understand the process from beginning to end.

In this article, I’ll show you how to build your own React UI library from scratch. It uses storybook as a UI documentation tool, rollup as a package, and supports less and Typescript.

The default environment

Due to the length, this article assumes that you already have the following environment and conditions:

  1. The Node environment (v12.19.0)
  2. NPM (v6.14.8)
  3. Create your own Github account
  4. An NPM account of your own

Of course, Node and NPM environments are not so limited, but I’m just telling you that my development environment is easy to use

Making preparation

Before starting the project, we will create a new repository of our own on Github

Now, you can in your making project got a SSH link, similar to this: [email protected]: yourname/basic – components. Git

Infrastructure projects

Create a base project, create a new folder called basic-Components, go to CD, and use git init to create a.git folder

mkdir basic-components
cd basic-components
git init
Copy the code

Use NPM init to initialize package.json, and enter each command directly. We will modify the configuration later.

npm init
Copy the code

In addition to the package.json file, we also need to create a readme. md file and a.gitignore file for uploading to the Github repository

# .gitignore
node_modules
packages/*/lib
packages/*/legacy/dist
.vscode
.DS_Store
Copy the code
# README.md
your own React component library using Rollup, TypeScript, Less and Storybook
Copy the code

Our current project should have a structure like this:

.git/
.gitignore
package.json
README.md
Copy the code

Connect your warehouse

These files are enough for now, now we need to associate our local project with the online project, we use the following command to associate the local basic-Components with the Github repository

#Temporary deposit
git add . 
#Make a COMMIT operation
git commit -m"component library first commit" 
#Associated remote Repository, remember to change to your SSH link
git remote add origin [email protected]:yourname/basic-components.git 
#Push the code
git push -u origin master 
Copy the code

The new github default branch should be main. You can use either Main or Master as your branch, which is OK. Here I cut the master branch to defualt

OK, now prepare your component

Run the following command to install the React and TypeScript dependencies

NPM I [email protected] [email protected] [email protected] @types/[email protected] @types/ [email protected] --saveCopy the code

storybook

With that installed, now let’s install the storybook and the Babel used

Storybook itself is an open source tool for developing UI components independently. It supports React, Vue, and Angular. Each component has a separate development debug environment and runs outside the main application, so it is independent of specific development environments and dependencies.

Here is the official description:

Storybook is an open source tool for building UI components and pages in isolation. It streamlines UI development, testing, and documentation. Storybook provides a sandbox to build UIs in isolation so you can develop hard-to-reach states and edge cases. Stories are a pragmatic, reproducible way to keep track of UI edge cases. Write stories once then reuse them to power automated tests. Stories show how UIs actually work not just how they’re supposed to work. That makes gathering feedback and reproductions easy.

This project is currently using Storybook 6, not much changed from Storybook 5, so it’s OK if you want to use version 5 storybook.

Do not use the NPX sb init command to init a storybook initial project directly. We start with no components.

NPM i@storybook /[email protected] [email protected] [email protected] [email protected] port [email protected] - DCopy the code

After the dependencies are installed, create a new.storybook folder in the root directory and create two new files: main.js and preview.js

// .storybook/main.js
// This is the storybook configuration file where loader, entry file, etc are configured
const path = require("path");

module.exports = {
  // The target file of the storybook document
  stories: [".. /packages/**/*.stories.tsx"].// Plugin dependencies, which we'll use later
  addons: [].webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.less$/,
      use: ["style-loader"."css-loader"."less-loader"].include: path.resolve(__dirname, ".. /")}); config.module.rules.push({test: /\.(ts|tsx)$/,
      loader: require.resolve("babel-loader"),
      options: {
        presets: [["react-app", { flow: false.typescript: true}}}]]); config.resolve.extensions.push(".ts".".tsx");

    returnconfig; }};Copy the code
// .storybook/preview.js

Copy the code

Create a new Babel configuration file in the root directory: babel.config.js

// babel.config.js
module.exports = {
  presets: [['@babel/preset-env',
      {
        targets: {
          node: 'current',}},],'@babel/preset-typescript'.'@babel/preset-react']};Copy the code

Add two lines of storybook related scripts to the package

{
  / /... other old
  "scripts": {
    "sb": "start-storybook -p 6006"."build:sb": "build-storybook -c .storybook -o docs"
  },
  / /... other old
}
Copy the code

This section has a lot of dependencies to install, so the current package.json file is posted here for you to copy directly to your own package.json file. You can install all dependencies in the root directory using the NPM I command.

{
  "name": "basic-components"."version": "1.0.0"."description": ""."main": "index.js"."scripts": {
    "sb": "start-storybook -p 6006"."build:sb": "build-storybook -c .storybook -o docs"
  },
  "author": ""."license": "ISC"."dependencies": {
    "@types/react": "^ 16.14.14"."@types/react-dom": "^ 16.9.14"."react": "^ 16.13.1"."react-dom": "^ 16.13.1"."typescript": "^ 3.8.3"
  },
  "devDependencies": {
    "@storybook/react": "^ 6.3.7." "."babel-loader": "^ 8.2.2"."babel-preset-react-app": "^ 10.0.0"."less": "^ 4.1.2." "."less-loader": "^ 5.0.0"."style-loader": "^ 1.3.0"."ts-loader": "^ 6.0.4"}}Copy the code

The sample components

Now to prepare some demo components, create a new folder in the root directory, create a new TextView folder, and create three files: index.tsx, index.less, and index.stories.tsx

Index.stories.tsx is the file used for storybook preview

// packages/TextView/index.tsx
import React from 'react';
import './index.less'

interfaceTextViewProps { children? : React.ReactNode }const TextView = ({ children }: TextViewProps) = > {
  return <div className='text-view'>
    {children}
  </div>
}

export default TextView;
Copy the code
/* packages/TextView/index.less */
.text-view {
  font-size: 24px;
  line-height: 40px;
  font-family: 'Times New Roman', Times, serif;
}
Copy the code
// packages/TextView/index.stories.tsx
import React from "react";
import TextView from "./index";

export default {
  title: "TextView"
};

export const WithTextView = () = > (
  <TextView>
    This is my test component
  </TextView>
);
Copy the code

Once created, run the following command in the root directory to view your TextView component

npm run sb
Copy the code

If you haven’t missed anything so far, your current folder should look like this. If you failed to run NPM run sb, you probably missed some files or configuration. Go back to the top of the article and check again.

.git/ .storybook/ main.js preview.js node_modules/ packages/ TextView/ index.less index.stories.tsx index.tsx .gitignore  babel.config.js package-lock.json package.json README.mdCopy the code

If the startup is successful, you should be able to see one of these local web pages

Run NPM run build:sb and you’ll see a static web folder called docs/. Run the index.html file in your browser and you should see the same page as when you run it alone. This page will be useful later, but we can ignore it for now. Wait to upload to Github.

A rollup packaging

Our component library needs to be sent to NPM for use as a library, so we need to add packaging capabilities to our component library before we release it.

The packaging tool we use here is rollup, which is a module packaging tool. The following is the official description

Rollup is a JavaScript module wrapper that compiles small pieces of code into large, complex pieces of code, such as libraries or applications. Rollup uses new standardized formats for code modules that are included in the ES6 version of JavaScript, rather than previous ad-hoc solutions such as CommonJS and AMD. ES6 modules allow you to use the most useful stand-alone functions in your favorite library freely and seamlessly, without having to carry around other unused code in your projects. ES6 modules will eventually be implemented natively in the browser, but the current Rollup gives you an early taste.

Rollup helps you start with an entry file and package all the module files you use into a final release file, so it’s great for building a library of tools. Now let’s add one more component

// packages/Mp4Player/index.tsx
import React from 'react'

export interface Mp4PlayerProps extends React.MediaHTMLAttributes<HTMLVideoElement> {
  url: string
}

const Mp4Player = ({ url, ... props }: Mp4PlayerProps) = > {
  return (
    <video src={url} autoPlay controls {. props} >
      <source src={url} type="video/mp4" />
      <track src={url} kind="captions" label="english_captions" />
    </video>)}export default Mp4Player
Copy the code
// packages/Mp4Player/index.stories.tsx
import React from "react";
import Mp4Player from "./index";

export default {
  title: "Mp4Player"
};

export const WithMp4Player = () = > (
  <Mp4Player
      controls={true}
      autoPlay={false}
      url="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/byted-player-videos/1.0.0/xgplayer-demo-720p.mp4"
      style={{
        width: "100%",
      }}
    />
);
Copy the code

Create a new index.ts file under the Packages folder and import the components separately

// packages/index.ts
export type { TextViewProps } from './TextView';
export { default as TextView } from "./TextView";
export type { Mp4PlayerProps } from './Mp4Player';
export { default as Mp4Player } from './Mp4Player';
Copy the code

It is worth noting that if your original project does not support this writing: Export type {TextViewProps} from ‘./TextView’ Export type {TextViewProps} from ‘./TextView’ Export type {TextViewProps} from ‘./TextView’ Export {TextViewProps} from ‘./TextView’ export {TextViewProps} from ‘./TextView’

Create a rollup.config.js file in your root directory. This file is an ES6 module that exposes an object containing rollup configuration options

// rollup.config.js
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import typescript from "rollup-plugin-typescript2";
import postcss from "rollup-plugin-postcss";
import json from "@rollup/plugin-json";
const { babel } = require("@rollup/plugin-babel");
const packageJson = require("./package.json");
const less = require("less");

const isProd = process.env.NODE_ENV === "production";

const babelOptions = {
  presets: ["@babel/preset-env"].extensions: ['.js'.'.jsx'.'.ts'.'.tsx'.'.less'].exclude: "**/node_modules/**"
};

const processLess = function(context, payload) {
  return new Promise((resolve, reject) = > {
    less.render(
      {
        file: context
      },
      function(err, result) {
        if(! err) { resolve(result); }else{ reject(err); }}); less.render(context, {}).then(function(output) {
        if (output && output.css) {
          resolve(output.css);
        } else{ reject({}); }},function(err) { reject(err); }); }); };export default {
  input: "packages/index.ts".output: [{file: packageJson.main,
      format: "cjs"
    },
    {
      file: packageJson.module,
      format: "es"}].plugins: [
    peerDepsExternal({ includeDependencies: !isProd }),
    resolve(),
    commonjs({ sourceMap: !isProd }),
    typescript({ useTsconfigDeclarationDir: true }),
    postcss({
      extract: true.process: processLess
    }),
    babel(babelOptions),
    json()
  ],
};
Copy the code

Those interested in Rollup configuration can access Rollup configuration

Create a tsconfig.json file in the root directory

{
  "compilerOptions": {
    "rootDir": "."."declaration": true."declarationDir": "./build/types"."module": "esnext"."target": "es5"."lib": ["es6"."dom"."es2016"."es2017"]."sourceMap": true."jsx": "react"."moduleResolution": "node"."allowSyntheticDefaultImports": true."esModuleInterop": true
  },
  "include": ["packages/**/*"]."exclude": [
    "node_modules"."dist"."docs"."packages/**/*.stories.tsx"."packages/**/*.test.tsx"]}Copy the code

Configure your package.json package (script, main, etc.) and place the rollup configuration in devDependencies. Run NPM I in the root directory to install it.

{
  "name": "jobsofferings-ui-components"."version": "0.0.1"."private": false."author": "jobsofferngs"."description": "your own React component library using Rollup, TypeScript, Less and Storybook"."main": "build/index.js"."module": "build/index.esm.js"."typings": "build/types/packages/index.d.ts"."files": [
    "build"]."types": "build/index.d.ts"."scripts": {
    "sb": "start-storybook -p 6006"."build": "rimraf build/* && rollup -c"."build:sb": "build-storybook -c .storybook -o docs"
  },
  "peerDependencies": {
    "react": "^ 16.13.1"."react-dom": "^ 16.13.1"."typescript": "3.8.3"
  },
  "dependencies": {
    "react": "^ 16.13.1"."react-dom": "^ 16.13.1"."typescript": "3.8.3"
  },
  "devDependencies": {
    "@types/react": "^ 16.14.14"."@types/react-dom": "^ 16.9.14"."@storybook/react": "^ 6.3.7." "."@rollup/plugin-babel": "^ 5.3.0." "."@rollup/plugin-commonjs": "^ 17.1.0"."@rollup/plugin-json": "^ 4.1.0." "."@rollup/plugin-node-resolve": "^ 11.2.1." "."rollup": "^ 2.56.3"."rollup-plugin-babel": "^ 4.4.0"."rollup-plugin-commonjs": "^ 10.1.0"."rollup-plugin-copy": "^ 3.4.0"."rollup-plugin-eslint": "^ 7.0.0." "."rollup-plugin-node-resolve": "^ 5.2.0." "."rollup-plugin-peer-deps-external": "^ 2.2.4." "."rollup-plugin-postcss": "^ 3.1.8"."rollup-plugin-terser": "^ 7.0.2"."rollup-plugin-typescript2": "^ 0.29.0"."rimraf": "^ 3.0.0"."babel-loader": "^ 8.2.2"."babel-preset-react-app": "^ 10.0.0"."less": "^ 4.1.2." "."less-loader": "^ 5.0.0"."style-loader": "^ 1.3.0"."ts-loader": "^ 6.0.4"}}Copy the code

You can use the NPM Pack to create a temporary NPM package and put it in your own project or create a test project in the root directory to test it.

At present, our project should have the following structure, and the files and folders that will not be submitted to Github have been removed

.storybook/
  main.js
  preview.js
build/
  types/
    ...
  index.css
  index.esm.css
  index.esm.js
  index.js
node_modules/
packages/
  TextView/
    index.less
    index.stories.tsx
    index.tsx
  Mp4Player/
    index.stories.tsx
    index.tsx
docs/
  ...
.gitignore
babel.config.js
package-lock.json
package.json
README.md
rollup.config.js
tsconfig.json
Copy the code

Release NPM package

As it is the React component library, we need to push the project to NPM so that others can use it on NPM. Remember to change your own name. I used jobsofferings- uI-Components as the name of the release package. You can download the package via NPM I jobsofferings- uI-components –save, where you can change the name you want to include, without missing new names

{
  "name": "jobsofferings-ui-components"."version": "0.0.1"./ /... Other configuration
}
Copy the code

By default, this is your first time to send packets, so in the root directory, run NPM adduser, enter your account password and email, if OTP authentication is enabled, you need to enter your OTP password once. If you are not a first-time package developer, such as your own library, you can run the NPM login command

Log in successfully, type NPM publish to publish the package, so that we can see the NPM package in the NPM library

Is this it?

You can think about what we are missing. Is this component library really ready for direct development?

  • Maybe, I mean maybe, you need a static page that you can display to give the user of the component a clearer description and support?
  • Besides the presentation of code, what else can we offer the user? Is markdown documentation adequate?
  • Using this library for development, how to switch between different properties to make their own debugging more convenient?
  • How about adding code for prettier?
  • So many commands to run in one release?
    Git add. Git commit -m"your commit info" NPM run build NPM version patch #Copy the code

Additional optimization

prettier with lint-staged

To add something to our component library, type the following command to install storybook’s plug-in and code prettier related library

NPM I @storybook/[email protected] @storybook/[email protected] @storybook/[email protected] Storybook /[email protected] [email protected] [email protected] [email protected] -dCopy the code

Add a few scripts and configurations to your package.json

{
  / /... other old
  "scripts": {
    "prettier": "prettier --write 'packages/**/*.{ts,tsx,less}'"."_____comment": "npm run git -- 'commit-msg' so you can push and update by a auto way"."git": "git add . && git commit -m"."postgit": "npm run build && npm version patch && npm publish && git push"."sb": "start-storybook -p 6006"."build": "rimraf build/* && rollup -c"."build:sb": "build-storybook -c .storybook -o docs"
  },
  / /... other old
  "lint-staged": {
    "packages/**/*.{ts,tsx,less}": [
      "prettier --write"]},"husky": {
    "hooks": {
      "pre-commit": "lint-staged"}}}Copy the code

Create a file in the root directory. Prettierrc

{
  "tabWidth": 2."useTabs": false."semi": true."singleQuote": false."trailingComma": "none"."arrowParens": "avoid"."bracketSpacing": true."endOfLine": "auto"."htmlWhitespaceSensitivity": "css"."jsxBracketSameLine": false."jsxSingleQuote": false."printWidth": 80
}
Copy the code
//. Prettierrc, no need to edit
{
  "tabWidth": 2.// Indent the number of Spaces
  "useTabs": false.// Use Spaces instead of TAB indentation
  "semi": true.// Use a semicolon at the end of a sentence
  "singleQuote": false.// Whether to use single quotation marks
  "trailingComma": "none".Print trailing commas if possible for multiple lines
  "arrowParens": "avoid".// Use parentheses around the arguments of the single-argument arrow function
  "bracketSpacing": true.// Whether to add Spaces before and after objects
  "endOfLine": "auto".// End the line form
  "htmlWhitespaceSensitivity": "css".// Not sensitive to HTML global whitespace
  "jsxBracketSameLine": false.// Multi-attribute HTML tag '>' folded line placement
  "jsxSingleQuote": false.// JSX uses single quotes
  "printWidth": 80 // Single line length
}
Copy the code

Here is the configuration file for Prettier, for example, you can look up the link for the actual configuration, for which the meaning of prettier has been added and deleted for reference here, and you can add or delete it yourself. After the configuration is complete, you can try a commit to see if the configuration is successful.

NPM run prettier the NPM run prettier command is used only to prettier –write a file before prettier has been prettier, or after the prettier configuration has been modified. Prettier –write prettier –write after git commit before commit

Of course, a current packages.json file is also provided for easy download

{
  "name": "jobsofferings-ui-components"."version": "0.0.1"."private": false."author": "jobsofferngs"."description": "your own React component library using Rollup, TypeScript, Less and Storybook"."main": "build/index.js"."module": "build/index.esm.js"."typings": "build/types/packages/index.d.ts"."files": [
    "build"]."types": "build/index.d.ts"."scripts": {
    "prettier": "prettier --write 'packages/**/*.{ts,tsx,less}'"."_____comment": "npm run git -- 'commit-msg' so you can push and update by a auto way"."git": "git add . && git commit -m"."postgit": "npm run build && npm version patch && npm publish && git push"."sb": "start-storybook -p 6006"."build": "rimraf build/* && rollup -c"."build:sb": "build-storybook -c .storybook -o docs"
  },
  "peerDependencies": {
    "react": "^ 16.13.1"."react-dom": "^ 16.13.1"."typescript": "3.8.3"
  },
  "dependencies": {
    "react": "^ 16.13.1"."react-dom": "^ 16.13.1"."typescript": "3.8.3"
  },
  "devDependencies": {
    "@rollup/plugin-babel": "^ 5.3.0." "."@rollup/plugin-commonjs": "^ 17.1.0"."@rollup/plugin-json": "^ 4.1.0." "."@rollup/plugin-node-resolve": "^ 11.2.1." "."@storybook/addon-actions": "^ 6.4.13"."@storybook/addon-docs": "^ 6.4.14"."@storybook/addon-info": "^ 5.3.21"."@storybook/addon-knobs": "^ 6.4.0"."@storybook/react": "^ 6.3.7." "."@types/react": "^ 16.14.14"."@types/react-dom": "^ 16.9.14"."babel-loader": "^ 8.2.2"."babel-preset-react-app": "^ 10.0.0"."husky": "^ 4.3.0"."less": "^ 4.1.2." "."less-loader": "^ 5.0.0"."lint-staged": "^ 10.5.3"."prettier": "^ 2.2.1." "."rimraf": "^ 3.0.0"."rollup": "^ 2.56.3"."rollup-plugin-babel": "^ 4.4.0"."rollup-plugin-commonjs": "^ 10.1.0"."rollup-plugin-copy": "^ 3.4.0"."rollup-plugin-eslint": "^ 7.0.0." "."rollup-plugin-node-resolve": "^ 5.2.0." "."rollup-plugin-peer-deps-external": "^ 2.2.4." "."rollup-plugin-postcss": "^ 3.1.8"."rollup-plugin-terser": "^ 7.0.2"."rollup-plugin-typescript2": "^ 0.29.0"."style-loader": "^ 1.3.0"."ts-loader": "^ 6.0.4"
  },
  "lint-staged": {
    "packages/**/*.{ts,tsx,less}": [
      "prettier --write"]},"husky": {
    "hooks": {
      "pre-commit": "lint-staged"}}}Copy the code
Development of the command

NPM run Git — “feat: Add dev script” Commit, build, publish, push

addon-actions & addon-knobs

Add a new file addons.js to the.storybook folder to import the two plug-ins

// .storybook/addons.js
import '@storybook/addon-actions/register';
import '@storybook/addon-knobs';
Copy the code

Then we register the Knobs and Docs plugin in addons of main.js

// .storybook/main.js
// This is the storybook configuration file where loader, entry file, etc are configured
const path = require("path");

module.exports = {
  // The target file of the storybook document
  stories: [".. /packages/**/*.stories.(tsx|mdx)"].// Plugin dependencies
  addons: ['@storybook/addon-knobs'.'@storybook/addon-docs'].webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.less$/,
      use: ["style-loader"."css-loader"."less-loader"].include: path.resolve(__dirname, ".. /")}); config.module.rules.push({test: /\.(ts|tsx)$/,
      loader: require.resolve("babel-loader"),
      options: {
        presets: [["react-app", { flow: false.typescript: true}}}]]); config.resolve.extensions.push(".ts".".tsx");

    returnconfig; }};Copy the code

Make a final change to our preview.js file

// .storybook/preview.js
import { addDecorator } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';
 
addDecorator(
  withInfo({
    header: false.inline: true}));Copy the code

With these three storybook configuration files modified, we are ready to add something different to our component documentation!

We began to do some modification on the TextView, now we revise the packages/TextView/index. The stories. The TSX composite file

// packages/TextView/index.stories.tsx
import React from "react";
import { action } from '@storybook/addon-actions';
import { Button } from '@storybook/react/demo';
import { boolean.number, select, text } from '@storybook/addon-knobs';
import TextView from "./index";

export default {
  title: "TextView"
};

export const WithTextView = () = > (
  <TextView>This is my test component</TextView>
);

// Use @storybook/addon-actions to record events
export const TestAddonActions = () = > (
  <Button
    onClick={action('clicked')}
  >
    <span role="img" aria-label="so cool">
      πŸ˜€ 😎 πŸ‘ πŸ’―
    </span>
  </Button>
);

// Use @storybook/addon-knobs to dynamically modify properties
export const TestAddonKnobs = () = > (
  <TextView
    children={text('children', 'children_value')} / >
);

// More examples
export const TestAddonKnobsMore = () = > (
  <input
    onClick={action('onClick')}
    onFocus={action('onFocus')}
    placeholder={text('placeholder', 'placeholder_value')}
    type={select('type'{password: "password", number: 'number', text: 'text'},number')}
    disabled={boolean('disabled', false)}
    size={number('size', 24)} / >
);
Copy the code

After the preview, you can see that clicking on the TestAddonActions button will print the event parameter, while switching to TestAddonKnobs will change the children value in the Knobs TAB below for dynamic updates.


You can test your components in this way, for example by typing extra long characters or null characters, to see if your component UI, interaction, or built-in requests work properly. A simple TestAddonKnobsMore component is provided as an example

Although it can be seen in the component below the Story Source can clearly see the display of the parameters of the component to use, however, can we have a plan, can let the user see both invoke the way, you can also use the markdown document for the history of the components, encapsulation, the description of the background, use technology such as information?

The MDX to

MDX is a format for writing JSX in Markdown documents. Using this file to write stories increased the flexibility of our component documents, and the writing itself was very similar to Markdown, making it much easier to learn

What is a Markdown? MDX official example

We’ll add an index.stories. MDX file to the Mp4Player folder

<! -- packages/Mp4Player/index.stories.mdx --> import { Meta, Story, Canvas } from "@storybook/addon-docs/blocks"; import Mp4Player from "./index.tsx"; <Meta title="MDX/Mp4Player" component={Mp4Player} /> ## Mp4Player ## Markdown #### # # # # # 5 # # # # # # 6 title title level title = = = = = = = = = = = = = = = = = secondary title -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - # # # foundation USES the following < Canvas > < Story name = "Mp4Player" > <Mp4Player controls={true} autoPlay={false} Url = "https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/byted-player-videos/1.0.0/xgplayer-demo-720p.mp4" style = {{width: "100%", }} /> </Story> </Canvas>Copy the code

In the preview, we can see that except for TSX files, normal Markdown documents can be used and parsed normally, which is a great improvement to our document development experience and user component use experience. With storyBook’s built-in HMR function, it is a great way to write documents.

Component documentation page

Finally, use the following command to submit your current temporary save to github. If the upload fails (Permission denied), please refer to the reference link

git add .
git commit -m"feat: init my ui components"
git push
Copy the code

Now go back to our Github repository, click Setting and scroll down to find the Github Page


Branch to branch, modifying folder for the docs, click save, wait for a few minutes later, you can see the domain name that starts with a https://yourname.github.io access to success, and show before the storybook static pages.

Note that if you don’t need the demo site, you can ignore the docs file and move it to.gitignore

The end of the

At this point, we have completed a simple UI component library:

  1. Supports React, Less, and TypeScript
  2. Rollup packaging is supported
  3. Support for Storybook as a documentation tool
  4. Support for hot Reload after component code changes (when developing components using the storybook documentation tool)
  5. Support for writing XMD documents
  6. Support publishing NPM
  7. Prettier with Lint-staged is supported
  8. Support for output of storybook static files
  9. You can view it on github page
  10. throughnpm i ${your-components-name} --saveMethod download.

Related links:

Prettier configuration document Prettier configuration guide – Editing Markdown MDX official example