Skip to content

Commit 61d7569

Browse files
Merge pull request #811 from inhibitor1217/docs/button
Write mdx documentation for Button component
2 parents 7d15371 + 535b20d commit 61d7569

File tree

4 files changed

+963
-5
lines changed

4 files changed

+963
-5
lines changed

.changeset/wise-apricots-switch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@channel.io/bezier-react": patch
3+
---
4+
5+
add storybook documentation for Button component
Lines changed: 371 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
import {
2+
useState,
3+
} from 'react'
4+
import {
5+
Canvas,
6+
Meta,
7+
Story,
8+
} from '@storybook/addon-docs'
9+
import base from 'paths.macro'
10+
import {
11+
getTitle,
12+
} from 'Utils/storyUtils'
13+
import {
14+
Avatar,
15+
} from 'Components/Avatars/Avatar'
16+
import {
17+
Button,
18+
ButtonSize,
19+
ButtonColorVariant,
20+
ButtonStyleVariant,
21+
} from 'Components/Button'
22+
import {
23+
ListItem,
24+
} from 'Components/ListItem'
25+
import {
26+
Overlay,
27+
OverlayPosition,
28+
} from 'Components/Overlay'
29+
import {
30+
SectionLabel,
31+
} from 'Components/SectionLabel'
32+
import {
33+
StackItem,
34+
HStack,
35+
VStack,
36+
} from 'Components/Stack'
37+
import {
38+
StatusType,
39+
} from 'Components/Status'
40+
import {
41+
Text,
42+
} from 'Components/Text'
43+
import {
44+
styled,
45+
Typography,
46+
} from 'Foundation'
47+
import {
48+
OverviewCTA,
49+
OverviewFloating,
50+
UsageAsync,
51+
UsageComposite,
52+
UsageCTA,
53+
UsageCTA2,
54+
UsageDropdown,
55+
UsageVariousContentsComposite,
56+
UsageVariousContentsCustom,
57+
UsageVariousContentsIconOnly,
58+
UsageWebLinks,
59+
VariantsColor,
60+
VariantsSize,
61+
VariantsStyle,
62+
} from './Button.stories'
63+
64+
<Meta
65+
title={getTitle(base)}
66+
parameters={{
67+
viewMode: 'docs',
68+
}}
69+
/>
70+
71+
# Button
72+
73+
## Overview
74+
75+
버튼은 클릭을 통해 사용자에게 액션을 제공하는 컴포넌트입니다.
76+
77+
버튼은 크게 4가지 사이즈로 나뉩니다. 그 중 M이 가장 보편적이며, 공간 절약을 위해 S가 쓰입니다. List나 Input 등 액션이 필요할 때는 XS도 사용할 수 있습니다. 가입, 초대 UX 등 굉장히 강조해야 할 버튼의 경우, L, XL 사이즈를 사용할 수 있습니다.
78+
79+
<Canvas>
80+
<Story story={OverviewCTA} />
81+
</Canvas>
82+
83+
<Canvas>
84+
<Story story={OverviewFloating} />
85+
</Canvas>
86+
87+
## Usage
88+
89+
### Recipe: Call to action
90+
91+
- 한 화면 내에서 CTA 버튼은 가능한 한, 가장 중요한 버튼 1개만 primary로 지정합니다. 후순위로 colored button을 같이 넣어야 할 경우에는 secondary로 넣습니다. 그 외에는 secondary, tetiary button을 조합하여 넣습니다.
92+
- 버튼 사이의 간격은 0 또는 6으로 합니다.
93+
94+
<Canvas>
95+
<Story story={UsageCTA} />
96+
</Canvas>
97+
98+
99+
<Canvas>
100+
<Story story={UsageCTA2} />
101+
</Canvas>
102+
103+
### Recipe: Web links
104+
105+
- 보통의 경우, tertiary button을 적절한 icon과 함께 사용합니다.
106+
107+
<Canvas>
108+
<Story story={UsageWebLinks} />
109+
</Canvas>
110+
111+
### Recipe: Composite Usage
112+
113+
- XS 크기의 버튼은 ListItem, SectionLabel 등 다른 컴포넌트에 함께 사용될 수 있습니다. 컴포넌트 좌우측에서 액션으로 사용됩니다.
114+
115+
<Story story={UsageComposite} />
116+
117+
### Recipe: Button with various contents
118+
119+
- 기본적으로 `leftContent`, `rightContent` prop에 icon name에 해당하는 string을 지정하여 좌우측에 아이콘이 들어가는 형태를 표현합니다.
120+
121+
<Canvas>
122+
<Story story={UsageVariousContentsComposite} />
123+
</Canvas>
124+
125+
- 아이콘만 들어가는 버튼의 경우, `leftContent` prop만 사용합니다.
126+
127+
<Canvas>
128+
<Story story={UsageVariousContentsIconOnly} />
129+
</Canvas>
130+
131+
- 아이콘 이외에 커스텀 컴포넌트가 들어가야 하는 상황에는, `leftContent`, `rightContent` prop에 `JSX.Element` 값을 지정할 수 있습니다.
132+
133+
<Canvas>
134+
<Story story={UsageVariousContentsCustom} />
135+
</Canvas>
136+
137+
### Recipe: Button with asynchronous actions
138+
139+
- 비동기적인 액션을 처리하는 경우, 액션이 처리중인 상태를 사용자에게 노출해야 하고, 액션이 처리중이라면 버튼을 비활성화하여 액션이 중복 처리되는 것을 막는 것이 보통의 경우입니다. `loading`, `disabled` prop을 통해 이 usecase를 구현할 수 있습니다.
140+
141+
```tsx
142+
const AsyncActionButton = () => {
143+
const [isFetching, setFetching] = useState(false)
144+
const handleClick = () => {
145+
setFetching(true)
146+
setTimeout(() => {
147+
setFetching(false)
148+
}, 1000)
149+
}
150+
return (
151+
<Button
152+
leftContent="play"
153+
text="Click Me!"
154+
colorVariant={ButtonColorVariant.Cobalt}
155+
styleVariant={ButtonStyleVariant.Primary}
156+
loading={isFetching}
157+
disabled={isFetching}
158+
onClick={handleClick}
159+
/>
160+
)
161+
}
162+
```
163+
164+
<Canvas>
165+
<Story story={UsageAsync} />
166+
</Canvas>
167+
168+
### Recipe: Button with dropdown
169+
170+
- 버튼을 눌러 dropdown, select 등 별도의 UI를 노출하는 경우, 해당 UI가 노출된 상태에서는 버튼이 "눌린 상태"를 유지하는 것이 자연스럽습니다.
171+
- `active` prop을 통해 버튼이 "눌린 상태" 임을 표현할 수 있습니다.
172+
173+
```tsx
174+
const OpenDropdownButton = () => {
175+
const [isOpen, setIsOpen] = useState(false)
176+
177+
return (
178+
<div>
179+
<Button
180+
text="Select"
181+
rightContent="triangle-down"
182+
active={isOpen}
183+
colorVariant={ButtonColorVariant.MonochromeLight}
184+
styleVariant={ButtonStyleVariant.Tertiary}
185+
onClick={() => setIsOpen(true)}
186+
/>
187+
188+
{ ... }
189+
</div>
190+
)
191+
}
192+
```
193+
194+
<Canvas>
195+
<Story story={UsageDropdown} />
196+
</Canvas>
197+
198+
## Variants
199+
200+
### Color Variants
201+
202+
- `ButtonColorVariant` enum을 통해 정의되며, `colorVariant` prop으로 지정할 수 있습니다.
203+
204+
<Story story={VariantsColor} />
205+
206+
### Style Variants
207+
208+
- `ButtonStyleVariant` enum을 통해 정의되며, `styleVariant` prop으로 지정할 수 있습니다.
209+
210+
<Story story={VariantsStyle} />
211+
212+
### Size
213+
214+
- `ButtonSize` enum을 통해 정의되며, `size` prop으로 지정할 수 있습니다.
215+
216+
<Story story={VariantsSize} />
217+
218+
## API
219+
220+
- `ButtonProps``BezierComponentProps`를 지원합니다.
221+
222+
<details>
223+
<summary><h3>ButtonSize</h3></summary>
224+
225+
```ts
226+
enum ButtonSize {
227+
XS,
228+
S,
229+
M,
230+
L,
231+
XL,
232+
}
233+
```
234+
</details>
235+
236+
<details>
237+
<summary><h3>ButtonColorVariant</h3></summary>
238+
239+
```ts
240+
enum ButtonColorVariant {
241+
Blue,
242+
Red,
243+
Green,
244+
Cobalt,
245+
Orange,
246+
Pink,
247+
Purple,
248+
MonochromeLight,
249+
MonochromeDark,
250+
251+
// @deprecated
252+
Monochrome,
253+
}
254+
```
255+
</details>
256+
257+
<details>
258+
<summary><h3>ButtonStyleVariant</h3></summary>
259+
260+
```ts
261+
enum ButtonStyleVariant {
262+
Primary,
263+
Secondary,
264+
Tertiary,
265+
Floating,
266+
}
267+
```
268+
</details>
269+
270+
<details>
271+
<summary><h3>ButtonProps</h3></summary>
272+
273+
```ts
274+
interface ButtonProps {
275+
/**
276+
* `type` attribute of typical HTML button.
277+
*
278+
* You may want to set `type` to `submit` to the button
279+
* which is used as a submit button in `<form>` component.
280+
*
281+
* @default 'button'
282+
*/
283+
type?: HTMLButtonElement['type']
284+
285+
/**
286+
* The text content in the button.
287+
*
288+
* Do not pass `text` prop if it is an icon-only button.
289+
*/
290+
text?: string
291+
292+
/**
293+
* The content displayed at left of the text content in the button.
294+
*/
295+
leftContent?: IconName | React.ReactNode
296+
297+
/**
298+
* The content displayed at right of the text content in the button.
299+
*/
300+
rightContent?: IconName | React.ReactNode
301+
302+
/**
303+
* If `loading` is true, spinner will be shown, replacing the content.
304+
*
305+
* @default false
306+
*/
307+
loading?: boolean
308+
309+
/**
310+
* If `active` is true, the button will be styled as if it is hovered.
311+
*
312+
* You may want to use this prop for a button which opens dropdown, etc.
313+
*
314+
* @default false
315+
*/
316+
active?: boolean
317+
318+
/**
319+
* Whether the button is disabled, and unable to interact.
320+
*
321+
* @default false
322+
*/
323+
disabled?: boolean
324+
325+
/**
326+
* The style variant.
327+
*
328+
* @default ButtonStyleVariant.Primary
329+
*/
330+
styleVariant?: ButtonStyleVariant
331+
332+
/**
333+
* The color variant.
334+
*
335+
* @default ButtonColorVariant.Blue
336+
*/
337+
colorVariant?: ButtonColorVariant
338+
339+
/**
340+
* The size variant.
341+
*
342+
* @default ButtonSize.M
343+
*/
344+
size?: ButtonSize
345+
346+
/**
347+
* The handler to be executed when the button is clicked.
348+
*/
349+
onClick?: React.MouseEventHandler
350+
351+
/**
352+
* The handler to be executed when the mouse enters the button.
353+
*/
354+
onMouseEnter?: React.MouseEventHandler
355+
356+
/**
357+
* The handler to be executed when the mouse leaves the button.
358+
*/
359+
onMouseLeave?: React.MouseEventHandler
360+
361+
/**
362+
* The handler to be executed when the button is unfocused.
363+
*/
364+
onBlur?: React.MouseEventHandler
365+
}
366+
```
367+
</details>
368+
369+
## Version
370+
371+
- Available since v0.3.28

0 commit comments

Comments
 (0)