Skip to content

Commit ddf8b35

Browse files
committed
refactor(toast): toast의 content를 string에서 react-node로 변경
1 parent 03d8735 commit ddf8b35

File tree

8 files changed

+102
-30
lines changed

8 files changed

+102
-30
lines changed

packages/bezier-react/src/components/Toast/Toast.stories.tsx

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ import { Story, Meta } from '@storybook/react'
77
/* Internal depependencies */
88
import { styled } from 'Foundation'
99
import { iconList, getTitle } from 'Utils/storyUtils'
10+
import { ProgressBar } from 'Components/ProgressBar'
11+
import { StackItem, VStack } from 'Components/Stack'
12+
import { Button, ButtonColorVariant, ButtonStyleVariant } from 'Components/Button'
1013
import useToast from './useToast'
1114
import ToastProvider from './ToastProvider'
1215
import ToastElement from './ToastElement'
13-
import ToastProps, { ToastAppearance, ToastPreset } from './Toast.types'
16+
import ToastProps, { ToastAppearance, ToastOptions, ToastPreset } from './Toast.types'
1417

1518
export default {
1619
title: getTitle(base),
@@ -206,3 +209,53 @@ export const WithZIndex: Story<ToastProps> = () => (
206209
</ToastProvider>
207210
</Container>
208211
)
212+
213+
function CustomContentToastController() {
214+
const toast = useToast()
215+
216+
const onClickCustomButtonInToast = useCallback(() => {
217+
toast.removeAllToasts()
218+
}, [toast])
219+
220+
const handleClick = useCallback((option?: ToastOptions) => {
221+
toast.addToast((
222+
<VStack spacing={6} align="stretch">
223+
<StackItem>
224+
<Button
225+
text="눌러주세요. 모든 토스트가 사라집니다."
226+
styleVariant={ButtonStyleVariant.Primary}
227+
colorVariant={ButtonColorVariant.Blue}
228+
onClick={onClickCustomButtonInToast}
229+
/>
230+
</StackItem>
231+
<StackItem>
232+
<ProgressBar
233+
width="100%"
234+
value={Math.random()}
235+
/>
236+
</StackItem>
237+
</VStack>
238+
), {
239+
preset: ToastPreset.Default,
240+
...option,
241+
})
242+
}, [
243+
toast,
244+
onClickCustomButtonInToast,
245+
])
246+
247+
return (
248+
<div>
249+
<button type="button" onClick={() => handleClick()}>default</button>
250+
<button type="button" onClick={() => handleClick({ autoDismiss: false })}>never dismiss</button>
251+
</div>
252+
)
253+
}
254+
255+
export const CustomContent: Story<ToastProps> = () => (
256+
<Container id="story-wrapper">
257+
<ToastProvider>
258+
<CustomContentToastController />
259+
</ToastProvider>
260+
</Container>
261+
)

packages/bezier-react/src/components/Toast/Toast.styled.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,16 @@ const getEllipsisColor = (
9595
)
9696

9797
export const Content = styled.div<Pick<ToastElementProps, 'actionContent' | 'onClick'>>`
98+
display: flex;
99+
flex: 1;
98100
margin: 3px 6px;
99101
overflow: hidden;
100102
color: ${({ actionContent, onClick, foundation }) => getEllipsisColor(actionContent, onClick, foundation)};
101103
`
102104

103105
export const EllipsisableContent = styled.div`
106+
display: flex;
107+
flex: 1;
104108
${ellipsis(5, LineHeightAbsoluteNumber.Lh18)};
105109
106110
overflow: visible;

packages/bezier-react/src/components/Toast/Toast.types.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* External dependencies */
2-
import { ReactNode, ComponentType } from 'react'
2+
import React, { ReactNode, ComponentType } from 'react'
33
import { noop } from 'lodash-es'
44

55
/* Internal dependencies */
@@ -44,6 +44,9 @@ interface ToastElementOptions {
4444
preset?: ToastPreset
4545
appearance?: ToastAppearance
4646
iconName?: IconName
47+
/**
48+
* @deprecated use React.ReactNode content props instead.
49+
*/
4750
actionContent?: string
4851
transitionDuration: TransitionDuration
4952
transform: InjectedInterpolation
@@ -53,9 +56,11 @@ interface ToastElementOptions {
5356
onDismiss: React.MouseEventHandler
5457
}
5558

59+
export type ToastContent = React.ReactNode
60+
5661
export default interface ToastElementProps extends
5762
BezierComponentProps,
58-
Required<ContentProps<string>>,
63+
Required<ContentProps<ToastContent>>,
5964
ToastElementOptions {}
6065

6166
export interface ToastProviderProps {
@@ -87,10 +92,10 @@ export const defaultOptions: ToastOptions = {
8792
rightSide: false,
8893
}
8994

90-
export type ToastType = ToastOptions & { id: ToastId, content: string }
95+
export type ToastType = ToastOptions & { id: ToastId, content: ToastContent }
9196

9297
export interface ToastContextType {
93-
add: (content: string, options: ToastOptions) => ToastId
98+
add: (content: ToastContent, options: ToastOptions) => ToastId
9499
remove: (id: ToastId) => void
95100
removeAll: () => void
96101
leftToasts: ToastType[]

packages/bezier-react/src/components/Toast/ToastController.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ function ToastController({
2020

2121
const handleDismiss = useCallback(() => {
2222
setTransform(initPosition(placement))
23-
timer.current = window.setTimeout(onDismiss, transitionDuration)
23+
timer.current = window.setTimeout(() => {
24+
onDismiss()
25+
}, transitionDuration)
2426
}, [
2527
onDismiss,
2628
placement,

packages/bezier-react/src/components/Toast/ToastElement.tsx

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* External dependencies */
22
import React, { Fragment, forwardRef, Ref, useMemo } from 'react'
33
import { v4 as uuid } from 'uuid'
4+
import { isString } from 'lodash-es'
45

56
/* Internal dependencies */
67
import { Typography } from 'Foundation'
@@ -27,28 +28,31 @@ const ToastElement = (
2728
}: ToastProps,
2829
forwardedRef: Ref<any>,
2930
) => {
30-
const newLineComponent = useMemo(() => (
31-
content.split('\n').map((str, index) => {
32-
if (index === 0) {
31+
const ToastContentComponent = useMemo(() => {
32+
if (isString(content)) {
33+
return content.split('\n').map((str, index) => {
34+
if (index === 0) {
35+
return (
36+
<Text key={uuid()} typo={Typography.Size14}>
37+
{ str }
38+
</Text>
39+
)
40+
}
41+
3342
return (
34-
<Text key={uuid()} typo={Typography.Size14}>
35-
{ str }
36-
</Text>
43+
<Fragment key={uuid()}>
44+
<br />
45+
<Text
46+
typo={Typography.Size14}
47+
>
48+
{ str }
49+
</Text>
50+
</Fragment>
3751
)
38-
}
39-
40-
return (
41-
<Fragment key={uuid()}>
42-
<br />
43-
<Text
44-
typo={Typography.Size14}
45-
>
46-
{ str }
47-
</Text>
48-
</Fragment>
49-
)
50-
})
51-
), [content])
52+
})
53+
}
54+
return content
55+
}, [content])
5256

5357
const {
5458
appearance: presetAppearance,
@@ -81,7 +85,7 @@ const ToastElement = (
8185
}}
8286
>
8387
<NormalContent>
84-
{ newLineComponent }
88+
{ ToastContentComponent }
8589
</NormalContent>
8690
{ ' ' }
8791
{ actionContent && onClick && (

packages/bezier-react/src/components/Toast/ToastProvider.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
ToastId,
1616
ToastProviderProps,
1717
ToastType,
18+
ToastContent,
1819
} from './Toast.types'
1920
import ToastContainer from './ToastContainer'
2021
import ToastController from './ToastController'
@@ -32,7 +33,7 @@ function ToastProvider({
3233
const [leftToasts, setLeftToasts] = useState<ToastType[]>([])
3334
const [rightToasts, setRightToasts] = useState<ToastType[]>([])
3435

35-
const add = useCallback((content: string, options: ToastOptions = defaultOptions) => {
36+
const add = useCallback((content: ToastContent, options: ToastOptions = defaultOptions) => {
3637
let result = ''
3738
if (options.rightSide) {
3839
result = rightToastService.add(content, options)
@@ -123,7 +124,7 @@ function ToastProvider({
123124
autoDismissTimeout={autoDismissTimeout}
124125
preset={preset}
125126
appearance={appearance}
126-
content={content}
127+
content={content || ''}
127128
iconName={iconName}
128129
component={ToastElement}
129130
onDismiss={() => handleDismiss(id, onDismiss)}

packages/bezier-react/src/components/Toast/ToastService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
ToastOptions,
88
ToastId,
99
ToastType,
10+
ToastContent,
1011
} from './Toast.types'
1112

1213
/* ToastService를 사용하는 이유
@@ -29,7 +30,7 @@ class ToastService {
2930
return this.toasts.reduce((flag, cur) => (cur.id === id ? true : flag), false)
3031
}
3132

32-
add = (content: string, options: ToastOptions = defaultOptions) => {
33+
add = (content: ToastContent, options: ToastOptions = defaultOptions) => {
3334
const newId: ToastId = uuid()
3435

3536
if (this.has(newId)) {

packages/bezier-react/src/components/Toast/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import ToastProps, {
88
ToastOptions,
99
ToastId,
1010
ToastType,
11+
ToastContent,
1112
} from './Toast.types'
1213

1314
export type {
1415
ToastProps,
1516
ToastOptions,
1617
ToastId,
1718
ToastType,
19+
ToastContent,
1820
}
1921

2022
export {

0 commit comments

Comments
 (0)