-
[React] Story book ๋ฆฌ์กํธ ์คํ ๋ฆฌ๋ถJavaScript/Storybook 2023. 3. 23. 11:03728x90๋ฐ์ํ
๐ story book์ด๋?
story book์ด๋, UI ์ปดํฌ๋ํธ๋ฅผ ๋ ๋ฆฝ์ ์ผ๋ก ๋ถ๋ฆฌํด ๊ฐ๋ณ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ํ ์คํธํ ์ ์๋๋ก ๋์์ฃผ๋ ๋๊ตฌ์ ๋๋ค.
story book ํ ํ๋ฆฟ ์ฌ์ฉํด๋ณด๊ธฐ
# ์คํ ๋ฆฌ๋ถ ํ ํ๋ฆฟ cloneํ๊ธฐ $ npx degit chromaui/intro-storybook-react-template taskbox $ cd taskbox # dependencies ์ค์นํ๊ธฐ $ yarn
story book์ผ๋ก Task ์ปดํฌ๋ํธ ์์ฑํ๊ธฐ
- title – task๋ฅผ ์ค๋ช ํด์ฃผ๋ ๋ฌธ์์ด
- state - ํ์ฌ ์ด๋ค task๊ฐ ๋ชฉ๋ก์ ์์ผ๋ฉฐ, ์ ํ๋์ด ์๋์ง์ ์ฌ๋ถ
๋จผ์ src/components/Task.js์ src/components/Task.stories.js์ ๋ ํ์ผ์ ์์ฑํฉ๋๋ค.
๐ src/components/Task.js
import React from 'react'; export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) { return ( <div className="list-item"> <input type="text" value={title} readOnly={true} /> </div> ); }
๐ src/components/Task.stories.js
import React from 'react'; // ์ฌ์ฉํ ์ปดํฌ๋ํธ import import Task from './Task'; export default { component: Task, // ์คํ ๋ฆฌ๋ถ์ ๋ํ๋ผ ์ปดํฌ๋ํธ title: 'Task', // title: ์คํ ๋ฆฌ๋ถ์ ๋ํ๋ ์ด๋ฆ [optional] }; const Template = (args) => <Task {...args} />; // Task ์ปดํฌ๋ํธ default ๋ฒ์ export const Default = Template.bind({}); Default.args = { task: { id: '1', title: 'Test Task', state: 'TASK_INBOX', updatedAt: new Date(2021, 0, 1, 9, 0), }, }; // Task ์ปดํฌ๋ํธ pinned ๋ฒ์ export const Pinned = Template.bind({}); Pinned.args = { task: { ...Default.args.task, // default Task ์ปดํฌ๋ํธ์ ๊ฐ์ ๋ด์ฉ state: 'TASK_PINNED', }, }; // Task ์ปดํฌ๋ํธ archived ๋ฒ์ export const Archived = Template.bind({}); Archived.args = { task: { ...Default.args.task, state: 'TASK_ARCHIVED', }, };
์คํ ๋ฆฌ๋ ์ฃผ์ด์ง ์ํ์์์ ๋ ๋๋ง๋ ์์(์๋ฅผ ๋ค์๋ฉด, prop๊ฐ ํฌํจ๋ ์ปดํฌ๋ํธ)๋ฅผ ๋ฐํํ๋ ํจ์์ ๋๋ค. ์ด๋ ํจ์ํ ์ปดํฌ๋ํธ(Functional Component)์ ๊ฐ์ต๋๋ค.
๐ก Template.bind({})๋ ํจ์์ ๋ณต์ฌ๋ณธ์ ๋ง๋๋ ํ์ค JavaScript์ ํ ๊ธฐ๋ฒ์ ๋๋ค. ์ฐ๋ฆฌ๋ ์ด ๊ธฐ๋ฒ์ ์ฌ์ฉํ์ฌ ๊ฐ๊ฐ์ ์คํ ๋ฆฌ๊ฐ ๊ณ ์ ํ ์์ฑ(properties)์ ๊ฐ์ง๋ง ๋์ผํ ๊ฒฐ๊ณผ๋ฌผ์ ์ฌ์ฉํ๋๋ก ํ ์ ์์ต๋๋ค.
์ธ์(arguments) ๋๋ ๊ฐ๋จํ ์ค์ฌ์ args๋ฅผ ์ฌ์ฉํ์ฌ ์คํ ๋ฆฌ๋ถ์ ๋ค์ ์์ํ์ง ์๊ณ ๋ Controls addon์ผ๋ก ์ปดํฌ๋ํธ๋ฅผ ์ค์๊ฐ์ผ๋ก ์์ ํ ์ ์์ต๋๋ค. args์ ๊ฐ์ด ๋ณํ๋ฉด ์ปดํฌ๋ํธ๋ ํจ๊ป ๋ณํฉ๋๋ค.
์คํ ๋ฆฌ๋ฅผ ๋ง๋ค ๋ ์ฐ๋ฆฌ๋ ๊ธฐ๋ณธ task ์ธ์๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๊ฐ ์์ํ๋ task์ ํํ๋ฅผ ๊ตฌ์ฑํฉ๋๋ค. ์ด๋ ์ผ๋ฐ์ ์ผ๋ก ์ค์ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ธ๋ก ํ์ฌ ๋ง๋ค์ด์ง๋๋ค. ๋ค์ ๋งํ์ง๋ง exportํ๋ ๊ฒ์ ์ฐจํ ์คํ ๋ฆฌ์์ ์ด๋ฅผ ์ฌ์ฌ์ฉ ํ ์ ์๋๋ก ํด์ค๋๋ค.
์คํ ๋ฆฌ๋ถ ํ๊ฒฝ์ค์
์คํ ๋ฆฌ๋ถ ํ๊ฒฝ์ค์ ํ์ผ (.storybook/main.js)์ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํฉ๋๋ค.
๐ .storybook/main.js
module.exports = { stories: ['../src/components/**/*.stories.js'], staticDirs: ['../public'], addons: [ '@storybook/addon-links', '@storybook/addon-essentials', '@storybook/preset-create-react-app', '@storybook/addon-interactions', ], features: { postcss: false, }, framework: '@storybook/react', core: { builder: 'webpack4', }, };
์์ ๊ฐ์ด .storybook ํด๋์ ๋ณ๊ฒฝ์ ๋ง์น์ จ๋ค๋ฉด, preview.js๋ฅผ ์๋์ ๊ฐ์ด ๋ณ๊ฒฝํฉ๋๋ค.
๐ .storybook/preview.js
import '../src/index.css'; //๐ Configures Storybook to log the actions( onArchiveTask and onPinTask ) in the UI. export const parameters = { actions: { argTypesRegex: '^on[A-Z].*' }, controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, };
๐ src/components/Task.js
import React from 'react'; export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) { return ( <div className={`list-item ${state}`}> <label className="checkbox"> <input type="checkbox" defaultChecked={state === 'TASK_ARCHIVED'} disabled={true} name="checked" /> <span className="checkbox-custom" onClick={() => onArchiveTask(id)} id={`archiveTask-${id}`} aria-label={`archiveTask-${id}`} /> </label> <div className="title"> <input type="text" value={title} readOnly={true} placeholder="Input title" /> </div> <div className="actions" onClick={event => event.stopPropagation()}> {state !== 'TASK_ARCHIVED' && ( // eslint-disable-next-line jsx-a11y/anchor-is-valid <a onClick={() => onPinTask(id)}> <span className={`icon-star`} id={`pinTask-${id}`} aria-label={`pinTask-${id}`} /> </a> )} </div> </div> ); }
๊ณต์ ๋ฌธ์ ์ฐธ์กฐ
https://storybook.js.org/tutorials/intro-to-storybook/react/ko/get-started/
LIST'JavaScript > Storybook' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Storybook] ๋ฆฌ์กํธ ์คํ ๋ฆฌ๋ถ ์ฌ์ฉํ๊ธฐ _TypeScript (0) 2023.04.07