Storybook

Ahyeon, Jung·2023년 10월 13일
0

Storybook

React, Angular, Vue 등의 분리된 UI 컴포넌트를 체계적이고 효율적으로 구축할 수 있는 개발, 테스트 및 문서화하는 도구
컴포넌트의 독립적인 시각적 개발 및 테스트 환경 설정가능

  • 컴포넌트 시각화: 각 컴포넌트의 다양한 상태를 시각화하고 테스트 가능
  • 독립적 테스트 환경: 각각의 스토리는 독립된 테스트 환경을 가지며 다양한 입력 데이터, 상태 및 이벤트를 시뮬레이션하여 컴포넌트의 동작을 테스트 가능
  • 문서화: Storybook을 사용하여 컴포넌트를 문서화하고 사용자 지침을 제공 가능. 다른 개발자나 디자이너에게 컴포넌트를 설명하고 사용법을 제공 가능

Component Story Format, CSF

스토리북이 인식할 수 있는 형식
.stories.js
.stories.tsx
*.stories.jsx

import React from 'react';
import { Button } from './Button';

export default {
  title: 'Example/Button',
  component: Button,
  args: {
    backgroundColor: '#000'
  },
  argTypes: {
    backgroundColor: { control: 'color' },
  },
};

title

Storybook의 사이드바에 표시될 이름. /로 구분할 경우 그룹과 스토리 이름 구분 가능 그룹명/스토리명

title: 'Example/Button'
Example 그룹의 Btton 스토리

component

컴포넌트

args

모든 스토리엥 공통으로 전달될 props

backgroundColor: '#000'
모든 스토리 공통으로 컴포넌트에게 backgroundColor: '#000'을 전달

argTypes

각 Story args의 행동 방식 설정

backgroundColor: { control: 'color' }
controls에서 선택한 컬러를 컴포넌트의 props로 전달할 것임

decorators

Story를 래핑하는 추가 렌더링 기능

parameters

Story에 대한 정적 메타 데이터 정의

excludeStories

렌더링 제외 설정

Addon

Storybook의 확장 기능. Storybook의 기능과 사용자 정의 기능을 확장하고 향상시키는 데 사용

Actions

컴포넌트에서 발생한 이벤트를 Storybook UI에서 기록하고 표시. 컴포넌트의 상호작용 및 이벤트 처리를 시각적으로 테스트하고 문서화 가능

Knobs

Storybook에서 컴포넌트의 props를 실시간으로 조절하게 해줌. 컴포넌트의 다양한 상태 및 설정을 시뮬레이션하고 테스트 가능

Vieport

다양한 화면 크기 및 미디어 쿼리 설정에서 컴포넌트를 미리 보기할 수 있는 환경을 제공 반응형 디자인 및 레이아웃을 테스트하고 확인 가능

Storyshots

스토리북 스토리를 사용하여 스냅샷 테스트를 생성하고 유지하는 데 도움이 되는 기능을 제공 스토리의 시각적 변화를 감지하여 버그를 미리 확인 가능

// Toast.tsx
interface MessageType {
  message: string;
}

// 에러 or 알림이 뜨면 toastState에 메시지를 추가
// toastState에 메시지가 있으면, toastList visible;
// item들은 특정 시간동안 toastState에 있다가, 시간이 지나면 or button 클릭하면 사라짐
const Toast = ({
  messages,
  handleSubmit,
}: {
  messages: MessageType[];
  handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
}) => {
  return (
    <div>
      <div style={{ backgroundColor: "pink", padding: "20px" }}>
        {messages.map((item: MessageType) => (
          <ToastItem
            key={item.message}
            message={item.message}
            messages={messages}
          />
        ))}
      </div>
      <form onSubmit={handleSubmit}>
        <input type="text" />
        <button>알림올리기</button>
      </form>
    </div>
  );
};

export default Toast;

const ToastItem = ({
  message,
  messages,
}: {
  message: string;
  messages: MessageType[];
}) => {
  useEffect(() => {
    const timer = setTimeout(() => {
      messages.shift();
    }, 5000);

    return () => {
      clearTimeout(timer);
    };
  }, [messages]);

  return (
    <div style={{ backgroundColor: "white", marginBottom: "10px" }}>
      <div>{message}</div>
    </div>
  );
};
// Toast.stories.tsx
const meta = {
  title: "Toast",
  component: Toast,
  decorators: [
    // story에 임의의 wrapper를 제공
    (story: any) => <div style={{ padding: "3rem" }}>{story()}</div>,
  ],
};
export default meta;

const Template = (args: any) => <Toast {...args} />;

export const Default: any = Template.bind({});
Default.args = {
  messages: [{ message: "안녕하세요" }, { message: "알림입니다" }],
  handleSubmit: (e: React.FormEvent<HTMLFormElement>) => {
    Default.args.messages.append(e.currentTarget.value);
  },
};

23.10.19 recoilRoot 감싸고 input으로 상태에 추가하기 성공

Reference

https://storybook.js.org/docs/react/writing-stories/introduction

profile
https://a-honey.tistory.com/

0개의 댓글