Global 다이얼로그 사용에 대한 내용입니다.
해당 기능은 공통업무 기능입니다. 다음과 같이 미리 준비된 Boilerplate confy-app 형태로 제공됩니다.
/src/shared/provider/customDialogProvider.ts
'use client'
import { DialogContext } from '@/shared/hooks/useDialog'
import { Button, Dialog, Flex, VisuallyHidden } from '@confy-ui/react/themes'
import { ReactNode, useCallback, useState } from 'react'
type DialogHelpers = {
resolve: (v: boolean) => void
close: () => void
}
interface DialogState {
type?: 'alert' | 'confirm'
open: boolean
/** 다이얼로그의 제목(좌측상단 볼드체) */
title?: string
/** 다이얼로그의 본문내용 */
description?: string
/** 컴포넌트 자체를 내려줄 수 있음 */
body?: ReactNode
/** 확인버튼 텍스트(default: 확인) */
confirmText?: string
/** 확인버튼 콜백함수(인자에서 close를 꺼내쓴다_그러지 않고 await처리도 가능) */
onConfirm?: (helpers: DialogHelpers) => void | Promise<void>
/** 취소버튼 텍스트(default: 취소) */
cancelText?: string
/** 취소버튼 콜백함수(인자에서 close를 꺼내쓴다_그러지 않고 await처리도 가능) */
onCancel?: (helpers: DialogHelpers) => void | Promise<void>
resolve: (v: boolean) => void
}
export type ShowDialogArgs = Omit<DialogState, 'open' | 'resolve' | 'id'>
export function DialogProvider({ children }: { children: ReactNode }) {
// ✅ 다이얼로그 스택(여러개 중첩 가능)
const [stack, setStack] = useState<DialogState[]>([])
// ✅ showDialog는 화면에서 사용할 메소드(프로미스 리턴하여 비동기 코드 처리 가능)
const showDialog = useCallback(
({ type, ...args }: ShowDialogArgs): Promise<boolean> => {
return new Promise((resolve) => {
const dialog: DialogState = {
type: type ?? 'alert',
...args,
open: true,
resolve
}
setStack((prev) => [...prev, dialog])
})
},
[]
)
//✅ JSX 리턴
return (
<DialogContext.Provider value={{ showDialog }}>
{children}
{stack.map((dialog, index) => {
const confirmHelpers: DialogHelpers = {
resolve: dialog.resolve,
close: () => {
dialog.resolve(true)
setStack((prev) => prev.slice(0, -1))
}
}
const cancelHelpers: DialogHelpers = {
resolve: dialog.resolve,
close: () => {
dialog.resolve(false)
setStack((prev) => prev.slice(0, -1))
}
}
const handleCancel = () => {
if (dialog.onCancel) {
dialog.onCancel(cancelHelpers)
} else {
cancelHelpers.close()
}
}
const handleConfirm = () => {
if (dialog.onConfirm) {
dialog.onConfirm(confirmHelpers)
} else {
confirmHelpers.close()
}
}
const handleOutsideClick = () => {
setStack((prev) => prev.slice(0, -1))
}
return (
<Dialog.Root
key={index}
open={dialog.open}
onOpenChange={handleOutsideClick}
>
<Dialog.Content maxWidth='450px' size='2'>
<Dialog.Title>
{dialog.title ?? (
<VisuallyHidden>
{dialog.description ?? '확인창'}
</VisuallyHidden>
)}
</Dialog.Title>
{dialog.description && (
<Dialog.Description size='2'>
{dialog.description}
</Dialog.Description>
)}
{dialog.body}
<Flex gap='2' mt='4' justify='end'>
{dialog.type === 'confirm' && (
<Button variant='outline' color='gray' onClick={handleCancel}>
{dialog.cancelText ?? '취소'}
</Button>
)}
<Button
variant='solid'
className='btn primary'
onClick={handleConfirm}
>
{dialog.confirmText ?? '확인'}
</Button>
</Flex>
</Dialog.Content>
</Dialog.Root>
)
})}
</DialogContext.Provider>
)
}
Global Context를 통해 다이얼로그를 관리 합니다stack에 다이얼로그를 저장 합니다.stack에서 제거 됩니다import { useDialog } from '@/shared/hooks/useDialog'
import { Button } from '@confy-ui/react/themes'
export default function Page2() {
const showDialog = useDialog()
const onClickButton = (data: { name: string; email: string }) => {
const tf = await showDialog({ description: 'Index 3) 모달_Cancel' })
if (tf) {
console.log('확인')
} else {
console.log('취소')
}
}
return (
<Button onClick={onClickButton}>show dialog</Button>
)
}
useDialog 사용시 확인 취소 값을 boolean값으로 리턴 해줍니다alert 타입과 confirm 타입을 선택 가능 합니다| Prop | Type | Default |
|---|---|---|
type | enum | alert |
title | string | No default value |
description | string | No default value |
body | ReactNode | No default value |
confirmText | string | 확인 |
cancelText | string | 취소 |