스토리북의 기본 사용방법에 대해 Vite + React + TypeScript 환경에 Storybook v7.0 도입하기 (1) 에서 학습했다. 이번에는 Storybook을 더 잘 사용하기 위한 몇 가지 방법들을 활용해보려고 한다.
현재 기본적으로 Controls
, Actions
, Interaction
, Knobs
패널이 존재한다. 여기에 컴포넌트의 코드를 바로 확인할 수 있도록 Code
panel을 추가하려고 한다.
간단하게 @storybook/addon-storysource
를 설치하고, addons에 규칙을 추가해주면 된다.
yarn add @storybook/addon-storysource --dev
// .storybook/main.js
module.exports = {
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-mdx-gfm',
'@storybook/addon-knobs',
**'@storybook/addon-storysource',** // 추가
],
...
};
그러면 하단에 Code 패널이 생성된다.
Storybook 자체가 프론트엔드 개발의 문서화를 지원한다. 그래서 컴포넌트 테스트용 목적 외에도 프로젝트를 소개하는 페이지를 추가하고자 한다.
우선 완성된 결과물은 다음과 같다. 좌측에 GETTING STARTED와 COMPONENTS 그룹을 생성했고, 프로젝트에 대한 소개인 Intro
페이지, 프로젝트에서 사용되는 icons를 정의한 Icons
페이지, 컬러토큰을 정의한 Palette
페이지, 폰트 관련 서식을 정의한 Typography
페이지를 추가로 구성했다.
다음과 같이 파일을 그룹핑하는 방법부터 알아보자. stories.(tsx|mdx)
파일을 생성한 후, title에서 이를 설정할 수 있다.
Button 컴포넌트를 예로 들면, 아래와 같이 title에 /
separator를 이용하면 그룹끼리 묶일 수 있다.
// src/components/Button/Button.stories.tsx
import Button from './Button';
export default {
title: 'Components/Button',
component: Button,
};
추가적으로, 정렬하는 방법에 대해 알아보자.
좌측 메뉴의 순서는 기본적으로 추가된 페이지 순으로 정렬되는데, 이러한 규칙을 알파벳 오름차순으로 정렬시키려면, 다음과 같이 parameters options의 storySort
를 이용한다.
method에 ‘alphabetical’을 추가하면 알파벳 순서로 스토리가 정렬된다. 이밖에도, 특정 페이지를 맨 위나 맨 아래로 배치하고 싶은 경우가 있다면, order
규칙을 적용할 수 있다. 이는 사용자 임의로 순서를 결정짓는데, 아래와 같은 규칙을 통해 GETTING STARTED 그룹의 순서가 알파벳 규칙을 따르지 않는 것을 확인할 수 있다.
export default {
parameters: {
options: {
storySort: {
method: 'alphabetical',
order: [
'Getting Started',
['Intro', 'Icons', 'Palette', 'Typography'],
'Components',
],
},
},
},
};
이제 본격적으로 각 페이지를 작성해보자.
Getting Started
하위 페이지 생성을 위해 src/stories
경로에 각 파일들을 작성했고, 컴포넌트를 정의하는 용도가 아닌 markdown 문서를 작성하기 위한 페이지이기 때문에 확장자는 mdx로 작성했다.
다음 그림은 누가봐도 마크다운 문법으로 작성된 페이지다. Storybook에서 제공하는 API 가운데 Meta
를 이용해 title을 정의한다. 그리고 해당 페이지에 대한 내용은 다들 익숙한 md 문법으로 작성하면 된다!
// src/stories/intro.stories.mdx
import React from 'react';
import { Meta } from '@storybook/blocks';
import IconButton from '../components/IconButton';
import { ThemeProvider } from 'styled-components';
import { theme } from '../styles/theme';
<Meta title='Getting Started/Intro' />
<section style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', padding: '10px' }}>
# Classmate Design System
### Design foundations and components library
<div style={{ padding: '20px' }}>
<ThemeProvider theme={theme}>
<IconButton
name='github'
onClick={() => window.open('https://github.com/Dev-TeamOne/classmate-frontend', '_blank')}
/>
</ThemeProvider>
</div>
</section>
## Getting Started
Classmate는 실시간으로 강연자와 청중을 연결해주는 크라우드소싱 플랫폼입니다. 스토리북을 통해 UI에 사용되는 컴포넌트들을 테스트 해볼 수 있습니다.
### Install
git clone https://github.com/Dev-TeamOne/classmate-frontend.git
yarn && yarn storybook
## References
[Github](https://github.com/Dev-TeamOne)
[UI-Design](https://www.figma.com/file/MMPKJgUWaE5lbRxQzHDycJ/Classmate?node-id=73-1760&t=3xpZO33ms2zuejzm-0)
[Classmate-team-notion](https://shy-cannon-6ec.notion.site/Dev-TeamOne-76767fce51764a35abe0c562753e580c)
이 역시도 Storybook에서 기본 API를 제공한다. IconGallery를 통해 프로젝트에서 사용되는 아이콘들을 grid 형태로 진열시킨다. IconGallery의 children으로 IconItem들을 넣을 수 있다.
import React from 'react';
import { Meta, IconGallery, IconItem } from '@storybook/blocks';
import Icon from '../components/Icon';
import { icons } from '../components/Icon/utils';
<Meta title='Getting Started/Icons' />
# IconGallery
<IconGallery style={{ marginTop: '50px' }}>
{icons.map((key) => (
<IconItem name={key}>
<Icon name={key} />
</IconItem>
))}
</IconGallery>
ColorPalette도 사용법이 간단하다. ColorPalette 컴포넌트의 children으로 나타내는 색상의 ColorItem을 작성하면된다.
string
표시할 색상의 이름string
색상에 대한 추가설명string[] | { [key: string]: string }
표시할 색상 목록 (key:value 형태)예시의 grey와 같이 여러 색상으로 분리하려면 color에 순서대로 key:value를 추가해주면 된다.
<ColorItem
title='grey'
subtitle='greyscale'
colors={{ Grey1: '#888888', Grey2: '#BBBBBB', Grey3: '#D7D7D7' }}
/>
// stories/colors.stories.mdx
import { Meta, ColorPalette, ColorItem } from '@storybook/blocks';
import { colors } from '../styles/theme';
<Meta title='Getting Started/Palette' />
# Colors
<ColorPalette>
<ColorItem
title='primary1'
subtitle='서비스의 메인컬러로 사용'
colors={{ Primary1: '#4B9BFA' }}
/>
<ColorItem
title='primary2'
subtitle='서비스의 보조컬러로 사용'
colors={{ Primary2: '#BFDBFD' }}
/>
<ColorItem
title='primary3'
subtitle='서비스의 보조컬러로 사용'
colors={{ Primary3: '#005DCC' }}
/>
<ColorItem
title='primary4'
subtitle='서비스의 보조컬러로 사용'
colors={{ Primary4: '#F1FAFF' }}
/>
<ColorItem title='red' subtitle='오류 및 삭제 등에 사용' colors={{ Error: '#F45452' }} />
<ColorItem
title='titleActive'
subtitle='서비스의 보조컬러로 사용'
colors={{ TitleActive: '#000000' }}
/>
<ColorItem
title='grey'
subtitle='greyscale'
colors={{ Grey1: '#888888', Grey2: '#BBBBBB', Grey3: '#D7D7D7' }}
/>
<ColorItem title='offWhite' subtitle='서브 배경색으로 사용' colors={{ OffWhite: '#F6F6F6' }} />
<ColorItem title='White' subtitle='컴포넌트의 배경색으로 사용' colors={{ white: '#FFFFFF' }} />
<ColorItem
title='background'
subtitle='서비스의 배경색으로 사용'
colors={{ Background: '#F9F9F9' }}
/>
</ColorPalette>
Typeset block은 프로젝트에서 쓰이는 폰트를 나타내는 목적의 문서다. Typeset 컴포넌트의 props로 fontSizes 배열과 fontWeight, fontFamily 를 적용할 수 있으며, 예시 문구는 sampleText로 전달한다.
import React from 'react';
import { Meta, Typeset } from '@storybook/blocks';
import { theme } from '../styles/theme';
<Meta title='Getting Started/Typography' />
# Base Typography
**Font:** Noto Sans KR
**Weights:** 400(light), 500(text), 700(bold, title)
<Typeset fontSizes={[12, 14, 16, 18, 28, 32]} fontWeight={400} sampleText='Was he a beast if music could move him so?' />
<Typeset fontSizes={[12, 14, 16, 18, 28, 32]} fontWeight={500} />
<Typeset fontSizes={[12, 14, 16, 18, 28, 32]} fontWeight={700} />
이외에도 Storybook은 다양한 API를 지원한다. 조금 더 문서를 잘 작성하고 싶다면 storybook-docs-api 문서를 보면서 추가해보는 것을 추천한다.
https://storybook.js.org/addons/@storybook/addon-storysource
정리가 잘 된 글이네요. 도움이 됐습니다.