Dialog
Playground
TSX
'use client';
import { useState } from 'react';
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitleGroup,
DialogTitle,
DialogDescription,
DialogBody,
DialogActions,
Button,
type DialogSize,
} from '@mbsw/ui';
export default function Demo() {
const settings = {
"title": "Title",
"description": "description",
"content": "contents",
"actionLabel": "저장",
"cancelLabel": "취소",
"size": "sm",
"hasClose": true
};
const [open, setOpen] = useState(true);
return (
<Dialog open={open} onOpenChange={setOpen}>
<style>{`
.mbsw-dialog-overlay[data-state='closed'] {
animation-fill-mode: forwards;
}
`}</style>
<DialogTrigger asChild>
<Button variant="solid" tone="secondary">
open
</Button>
</DialogTrigger>
<DialogContent
style={{
animationFillMode: 'forwards',
maxWidth: 'calc(100% - 48px)',
}}
size={settings.size as DialogSize}
hasClose={settings.hasClose}
closeLabel={"대화상자 닫기"}
>
<DialogHeader>
<DialogTitleGroup>
<DialogTitle>{settings.title}</DialogTitle>
<DialogDescription style={{ whiteSpace: 'pre-wrap' }}>
{settings.description}
</DialogDescription>
</DialogTitleGroup>
</DialogHeader>
<DialogBody style={{ whiteSpace: 'pre-wrap' }}>
{settings.content}
</DialogBody>
<DialogActions>
<Button
variant="outline"
tone="secondary"
onClick={() => setOpen(false)}
>
{settings.cancelLabel}
</Button>
<Button onClick={() => setOpen(false)}>{settings.actionLabel}</Button>
</DialogActions>
</DialogContent>
</Dialog>
);
}
AlertDialog
AlertDialog는 명시적인 확인이나 취소가 필요한 중요한 결정에 사용합니다. 취소 버튼에 먼저 초점을 두며 Esc로 닫히지 않습니다.
TSX
'use client';
import {
Button,
AlertDialog,
AlertDialogTrigger,
AlertDialogContent,
AlertDialogHeader,
AlertDialogTitleGroup,
type DialogSize,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogActions,
AlertDialogAction,
AlertDialogCancel,
} from '@mbsw/ui';
export default function Demo() {
const settings = {
"title": "Title",
"description": "Description",
"actionLabel": "확인",
"cancelLabel": "취소",
"size": "sm"
};
return (
<>
<AlertDialog defaultOpen>
<style>{`
.mbsw-dialog-overlay[data-state='closed'] {
animation-fill-mode: forwards;
}
`}</style>
<AlertDialogTrigger asChild>
<Button tone="secondary">open</Button>
</AlertDialogTrigger>
<AlertDialogContent
size={settings.size as DialogSize}
style={{
animationFillMode: 'forwards',
maxWidth: 'calc(100vw - 32px)',
}}
>
<AlertDialogHeader>
<AlertDialogTitleGroup>
<AlertDialogTitle>{settings.title}</AlertDialogTitle>
<AlertDialogDescription style={{ whiteSpace: 'pre-wrap' }}>
{settings.description}
</AlertDialogDescription>
</AlertDialogTitleGroup>
</AlertDialogHeader>
<AlertDialogActions>
<AlertDialogCancel>{settings.cancelLabel}</AlertDialogCancel>
<AlertDialogAction asChild>
<Button variant="solid" tone="destructive">
{settings.actionLabel}
</Button>
</AlertDialogAction>
</AlertDialogActions>
</AlertDialogContent>
</AlertDialog>
</>
);
}
SplitDialog
TSX
'use client';
import { useState, useRef } from 'react';
import {
Button,
SplitDialog,
SplitDialogTrigger,
SplitDialogContent,
SplitDialogLayout,
SplitDialogActions,
DialogHeader,
DialogTitleGroup,
DialogTitle,
DialogDescription,
ScrollArea,
} from '@mbsw/ui';
export default function Demo() {
const settings = {
"secondaryContent": "Content B",
"title": "Title",
"description": "Description",
"content": "Content A",
"actionLabel": "확인",
"cancelLabel": "취소"
};
const [open, setOpen] = useState(true);
const contentRef = useRef<HTMLDivElement>(null);
return (
<SplitDialog open={open} onOpenChange={setOpen}>
<style>{`
.mbsw-dialog-overlay[data-state='closed'] { animation-fill-mode: forwards; }
.example-split-layout > [data-slot='split-dialog-left'] { width: auto; }
`}</style>
<SplitDialogTrigger asChild>
<Button tone="secondary" variant="solid">
open
</Button>
</SplitDialogTrigger>
<SplitDialogContent
ref={contentRef}
onOpenAutoFocus={(event) => {
event.preventDefault();
contentRef.current?.focus();
}}
style={{
animationFillMode: 'forwards',
width: 'min(960px, calc(100vw - 32px))',
height: 'calc(100dvh - 32px)',
maxHeight: 600,
gap: 16,
padding: 16,
}}
>
<DialogHeader>
<DialogTitleGroup>
<DialogTitle>{settings.title || 'Title'}</DialogTitle>
<DialogDescription style={{ whiteSpace: 'pre-wrap' }}>
{settings.description}
</DialogDescription>
</DialogTitleGroup>
</DialogHeader>
<SplitDialogLayout
className="example-split-layout"
style={{
display: 'grid',
gridTemplateColumns: 'minmax(0, 1fr) 1px minmax(0, 1fr)',
gap: 16,
}}
left={
<ScrollArea
style={{ width: '100%', height: '100%' }}
viewportProps={{ 'aria-label': 'Left content' }}
>
<div
style={{
padding: 12,
whiteSpace: 'pre-wrap',
overflowWrap: 'anywhere',
}}
>
{settings.content}
</div>
</ScrollArea>
}
right={
<ScrollArea
style={{ width: '100%', height: '100%' }}
viewportProps={{ 'aria-label': 'Right content' }}
>
<div
style={{
padding: 12,
whiteSpace: 'pre-wrap',
overflowWrap: 'anywhere',
}}
>
{settings.secondaryContent}
</div>
</ScrollArea>
}
/>
<SplitDialogActions>
<Button
variant="outline"
tone="secondary"
onClick={() => setOpen(false)}
>
{settings.cancelLabel}
</Button>
<Button onClick={() => setOpen(false)}>{settings.actionLabel}</Button>
</SplitDialogActions>
</SplitDialogContent>
</SplitDialog>
);
}
Usage
DialogContent는 배경과 포털, 닫기 버튼을 구성합니다. hasClose로 닫기 버튼 표시 여부를, closeLabel로 버튼 이름을 지정합니다. AlertDialog는 명시적으로 확인하거나 취소해야 하는 결정에, SplitDialog는 두 영역으로 나뉜 콘텐츠에 사용합니다.
TSX
'use client';
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitleGroup,
DialogTitle,
DialogDescription,
DialogBody,
Button,
} from '@mbsw/ui';
export default function Example() {
return (
<Dialog>
<DialogTrigger asChild>
<Button>open</Button>
</DialogTrigger>
<DialogContent size="sm" closeLabel={"대화상자 닫기"}>
<DialogHeader>
<DialogTitleGroup>
<DialogTitle>Title</DialogTitle>
<DialogDescription>description</DialogDescription>
</DialogTitleGroup>
</DialogHeader>
<DialogBody>contents</DialogBody>
</DialogContent>
</Dialog>
);
}
Playground의 Code 탭에서 현재 설정과 동작이 포함된 예제 전체를 복사할 수 있습니다. 공통 CSS 설치는 설치하기를 확인하세요.
Composition
AlertDialogAlertDialogActionAlertDialogActionsAlertDialogCancelAlertDialogContentAlertDialogDescriptionAlertDialogHeaderAlertDialogPortalAlertDialogTitleAlertDialogTitleGroupAlertDialogTriggerDialogDialogActionsDialogBodyDialogCloseDialogContentDialogDescriptionDialogHeaderDialogOverlayDialogPortalDialogTitleDialogTitleGroupDialogTriggerSplitDialogSplitDialogActionsSplitDialogCloseSplitDialogContentSplitDialogLayoutSplitDialogTrigger