React, Angular, Vue 등의 분리된 UI 컴포넌트를 체계적이고 효율적으로 구축할 수 있는 개발, 테스트 및 문서화하는 도구
컴포넌트의 독립적인 시각적 개발 및 테스트 환경 설정가능
스토리북이 인식할 수 있는 형식
.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' },
},
};
Storybook의 사이드바에 표시될 이름. /로 구분할 경우 그룹과 스토리 이름 구분 가능 그룹명/스토리명
title: 'Example/Button'
Example 그룹의 Btton 스토리
컴포넌트
모든 스토리엥 공통으로 전달될 props
backgroundColor: '#000'
모든 스토리 공통으로 컴포넌트에게 backgroundColor: '#000'
을 전달
각 Story args의 행동 방식 설정
backgroundColor: { control: 'color' }
controls에서 선택한 컬러를 컴포넌트의 props로 전달할 것임
Story를 래핑하는 추가 렌더링 기능
Story에 대한 정적 메타 데이터 정의
렌더링 제외 설정
Storybook의 확장 기능. Storybook의 기능과 사용자 정의 기능을 확장하고 향상시키는 데 사용
컴포넌트에서 발생한 이벤트를 Storybook UI에서 기록하고 표시. 컴포넌트의 상호작용 및 이벤트 처리를 시각적으로 테스트하고 문서화 가능
Storybook에서 컴포넌트의 props를 실시간으로 조절하게 해줌. 컴포넌트의 다양한 상태 및 설정을 시뮬레이션하고 테스트 가능
다양한 화면 크기 및 미디어 쿼리 설정에서 컴포넌트를 미리 보기할 수 있는 환경을 제공 반응형 디자인 및 레이아웃을 테스트하고 확인 가능
스토리북 스토리를 사용하여 스냅샷 테스트를 생성하고 유지하는 데 도움이 되는 기능을 제공 스토리의 시각적 변화를 감지하여 버그를 미리 확인 가능
// 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으로 상태에 추가하기 성공
https://storybook.js.org/docs/react/writing-stories/introduction