Storybook

Setup

$ npx create-react-app example-story-book
$ cd example-story-book
$ npm install @storybook/react --save-dev

story book 섀정을 μœ„ν•΄ .storybook 폴더 μ•„λž˜μ— config νŒŒμΌμ„ μΆ”κ°€ν•©λ‹ˆλ‹€.

// .storybook/config.js

import { configure } from "@storybook/react";

configure(require.context("../docs", true, /\.stories\.js$/), module);

config νŒŒμΌμΆ”κ°€ ν›„ story component 듀을 놓을 docs 폴더λ₯Ό μΆ”κ°€ν•΄μ£Όμ„Έμš” docs ν΄λ”μ˜ story component 듀은 *.stories.js μ΄λΌλŠ” νŒ¨ν„΄μ˜ 이름을 κ°€μ§‘λ‹ˆλ‹€.

storybook μ—μ„œ μ œκ³΅ν•΄μ£ΌλŠ” demo button 을 μΆ”κ°€ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

// docs/button.stories.js

import React from "react";

import { storiesOf } from "@storybook/react";
import { Button } from "@storybook/react/demo";

export default { title: "Button" };

storiesOf("Button Component", module)
  .add("withText", () => <Button>Hello Button</Button>)
  .add("withEmoji", () => (
    <Button>
      <span role="img" aria-label="so cool">
        πŸ˜€ 😎 πŸ‘ πŸ’―
      </span>
    </Button>
  ));

storiesOf λŠ” μ»΄ν¬λ„ŒνŠΈλ₯Ό μŠ€ν† λ¦¬ λ‹¨μœ„λ‘œ λ…ΈμΆœ ν•  수 있게 λ„μ™€μ€λ‹ˆλ‹€. 크게 Button Component λΌλŠ” μŠ€ν† λ¦¬λ‘œ λ¬Άμ–΄ λ…ΈμΆœν•©λ‹ˆλ‹€.

싀행을 μœ„ν•΄ package.json 의 scripts 에 storybook λͺ…λ Ήμ–΄λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.

// package.json
"scripts": {
  "docs": "start-storybook"
}
$ npm run docs

μš°λ¦¬κ°€ μœ„μͺ½μ—μ„œ story 에 μΆ”κ°€ν–ˆλ˜ button μ»΄ν¬λ„ŒνŠΈλ₯Ό 확인 ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό μ΄μš©ν•˜λ©΄ μƒνƒœμ— λ”°λ₯Έ μ»΄ν¬λ„ŒνŠΈ λ³€ν™” λ˜λŠ” λ””μžμΈ μ μš©μ—¬λΆ€λ₯Ό 미리 확인 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Component 좔가해보기

styled-components λ₯Ό μ΄μš©ν•˜μ—¬ 직접 κ΅¬μ„±ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

$ npm install --save styled-components

src 폴더 μ•„λž˜μ— input.js λΌλŠ” component λ₯Ό λ§Œλ“€μ–΄μ£Όμ„Έμš”

// src/input.js 

import styled, { css } from "styled-components";

const BaseInput = styled.input`
  width: 100%;
  padding: 14px;
  border-radius: 2px;
  border: solid 1px #efefef;
  background-color: #ffffff;
  font-size: 16px;
  outline: none;
  box-sizing: border-box;

  ${({ focus }) =>
    focus &&
    css`
      border: solid 1px #ff30ac;
    `}
`;

export default BaseInput;

input 은 focus props 에 따라 border style 이 λ³€ν•©λ‹ˆλ‹€. ν•΄λ‹Ή component λ₯Ό story book 에 μΆ”κ°€ν•©λ‹ˆλ‹€.

// docs/input.stories.js

import React from "react";
import { storiesOf } from "@storybook/react";
import Input from "../src/input";

export default { title: "Button" };

storiesOf("Input", module)
  .add("Base Input", () => <Input />)
  .add("Focus Input", () => <Input focus />);

Addon

addon 을 μΆ”κ°€ν•˜λ©΄ κΈ°λ³Έλ™μž‘ μ™Έ μ—¬λŸ¬κ°€μ§€ μž‘μ—…μ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

$ npm install -D @storybook/addon-knobs @storybook/addon-knobs/register

.storybook 폴더에 addons.js νŒŒμΌμ„ μΆ”κ°€ν•˜μ—¬ addons λ₯Ό λ“±λ‘ν•©λ‹ˆλ‹€.

// .storybook/addons.js

import "@storybook/addon-knobs/register";

config νŒŒμΌμ—λ„ μΆ”κ°€ν•΄μ•Όν•©λ‹ˆλ‹€.

// .storybook/config.js

import { configure, addDecorator } from "@storybook/react";
import { withKnobs } from "@storybook/addon-knobs";

addDecorator(withKnobs);

configure(require.context("../docs", true, /\.stories\.js$/), module);
$ npm run docs

addon κΈ°λŠ₯으둜 input 의 focus λ₯Ό μ‘°μ ˆν•˜λ„λ‘ μΆ”κ°€ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

// docs/input.stories.js

import React from "react";
import { storiesOf } from "@storybook/react";
import { boolean } from "@storybook/addon-knobs";
import Input from "../src/input";

storiesOf("Input", module)
  .add("Base Input", () => <Input focus={boolean("포컀슀", false)} />)
  .add("Focus Input", () => <Input focus />);

배포

Storybook 을 배포할 Github Repo λ₯Ό λ§Œλ“€μ–΄μ£Όμ„Έμš”

Github page 에 κ°„λ‹¨ν•˜κ²Œ 배포할 수 있게 λ„μ™€μ£ΌλŠ” λͺ¨λ“ˆμ„ μ„€μΉ˜ν•΄μ•Όν•©λ‹ˆλ‹€.

$ npm i @storybook/storybook-deployer --save-dev

μ„€μΉ˜ν›„ 배포 λͺ…λ Ήμ–΄λ₯Ό λ“±λ‘ν•©λ‹ˆλ‹€.

// package.json 

"scripts": {
  "docs": "start-storybook",
  "deploy": "storybook-to-ghpages"
}
$ npm run deploy 

μ•„μ£Ό κ°„λ‹¨ν•˜κ²Œ 배포가 κ°€λŠ₯ν•©λ‹ˆλ‹€.

배포 결과물은 <github name>.github.io/<repo name>

μ €μ˜ 경우 https://appear.github.io/example-storybook μž…λ‹ˆλ‹€.

Last updated