화면 중앙에 떠서 사용자의 주의를 모으고, 제목·본문·푸터를 담는 모달형 컴포넌트입니다.
import "./styles" ;
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { ActionButton } from "@seed-design/lynx-react" ;
export default function Example () {
return (
< DialogRoot >
< DialogTrigger >
< ActionButton variant = "neutralSolid" >Open Dialog</ ActionButton >
</ DialogTrigger >
< DialogContent title = "제목" description = "설명을 작성할 수 있어요" >
< DialogBody >
< text className = "dialog-example-text" >
본문에는 사용자가 확인해야 할 내용이나 추가 입력 폼을 배치할 수 있습니다.
</ text >
</ DialogBody >
< DialogFooter >
< view className = "dialog-example-actions" >
< DialogAction variant = "neutralWeak" >취소</ DialogAction >
< DialogAction variant = "neutralSolid" >확인</ DialogAction >
</ view >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
);
}
npx @seed-design/cli add ui:dialog pnpm dlx @seed-design/cli add ui:dialog yarn dlx @seed-design/cli add ui:dialog bun x @seed-design/cli add ui:dialog
의존성 설치
npm install @karrotmarket/lynx-monochrome-icon @seed-design/lynx-react yarn add @karrotmarket/lynx-monochrome-icon @seed-design/lynx-react pnpm add @karrotmarket/lynx-monochrome-icon @seed-design/lynx-react bun add @karrotmarket/lynx-monochrome-icon @seed-design/lynx-react 아래 코드를 복사 후 붙여넣고 사용하세요 /**
* @file ui:dialog
* @requires @seed-design/lynx-react@^1.0.0
* @requires @seed-design/lynx-css@^1.0.0
* @requires @karrotmarket/lynx-monochrome-icon@>=1.20.0 <2.0.0
**/
import IconXmarkLine from "@karrotmarket/lynx-monochrome-icon/IconXmarkLine" ;
import * as React from "@lynx-js/react" ;
import {
ActionButton,
Dialog as SeedDialog,
Icon,
type ActionButtonProps,
} from "@seed-design/lynx-react" ;
export interface DialogRootProps extends SeedDialog . RootProps {}
/**
* @see https://seed-design.io/lynx/components/dialog
*/
export const DialogRoot = SeedDialog.Root;
export interface DialogTriggerProps extends SeedDialog . TriggerProps {}
export const DialogTrigger = SeedDialog.Trigger;
export interface DialogBodyProps extends SeedDialog . BodyProps {}
export const DialogBody = SeedDialog.Body;
export interface DialogFooterProps extends SeedDialog . FooterProps {}
export const DialogFooter = SeedDialog.Footer;
export interface DialogActionProps
extends Omit < SeedDialog . ActionProps , "children" >,
ActionButtonProps {}
/**
* `ActionButton`을 닫기 동작과 함께 렌더링합니다. `disabled`·`loading`이면 닫지 않습니다.
*/
export const DialogAction = React. forwardRef < unknown , DialogActionProps >(
({ children , transition , ... actionButtonProps }, ref ) => {
const { disabled , loading } = actionButtonProps;
return (
< SeedDialog.Action transition = {transition} disabled = {disabled === true || loading === true }>
< ActionButton ref = {ref} { ... actionButtonProps}>
{children}
</ ActionButton >
</ SeedDialog.Action >
);
},
);
DialogAction.displayName = "DialogAction" ;
export interface DialogContentProps extends Omit < SeedDialog . ContentProps , "children" > {
title ?: React . ReactNode ;
description ?: React . ReactNode ;
children ?: React . ReactNode ;
container ?: SeedDialog . PositionerProps [ "container" ];
overlayLevel ?: SeedDialog . PositionerProps [ "overlayLevel" ];
/**
* @default true
*/
showCloseButton ?: boolean ;
}
/**
* Positioner, Backdrop, Header를 조립하고 제목·설명·닫기 ActionButton을 제공합니다.
*/
export const DialogContent = ( props : DialogContentProps ) => {
const {
children ,
title ,
description ,
container ,
overlayLevel ,
showCloseButton = true ,
... contentProps
} = props;
const shouldRenderHeader = title != null || description != null || showCloseButton;
return (
< SeedDialog.Positioner container = {container} overlayLevel = {overlayLevel}>
< SeedDialog.Backdrop />
< SeedDialog.Content { ... contentProps}>
{shouldRenderHeader ? (
< SeedDialog.Header >
< view
style = {{
display: "flex" ,
flexDirection: "row" ,
alignItems: "flex-start" ,
justifyContent: "space-between" ,
gap: "8px" ,
}}
>
< view style = {{ display: "flex" , flexDirection: "column" , flexGrow: 1 , gap: "6px" }}>
{title != null ? < SeedDialog.Title >{title}</ SeedDialog.Title > : null }
{description != null ? (
< SeedDialog.Description >{description}</ SeedDialog.Description >
) : null }
</ view >
{showCloseButton ? (
< SeedDialog.Action >
< view style = {{ margin: "-15px" }}>
< ActionButton
variant = "ghost"
size = "large"
layout = "iconOnly"
accessibility-label = "닫기"
>
< Icon icon = {< IconXmarkLine />} color = "fg.neutralSubtle" />
</ ActionButton >
</ view >
</ SeedDialog.Action >
) : null }
</ view >
</ SeedDialog.Header >
) : null }
{children}
</ SeedDialog.Content >
</ SeedDialog.Positioner >
);
};
DialogContent.displayName = "DialogContent" ;
/**
* This file is a snippet from SEED Design, helping you get started quickly with @seed-design/* packages.
* You can extend this snippet however you want.
*/
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { ActionButton } from "@seed-design/lynx-react" ;
export function App () {
return (
< DialogRoot size = "medium" >
< DialogTrigger >
< ActionButton variant = "neutralSolid" >다이얼로그 열기</ ActionButton >
</ DialogTrigger >
< DialogContent title = "제목" description = "부가 설명" >
< DialogBody >
< text >본문 콘텐츠</ text >
</ DialogBody >
< DialogFooter >
< DialogAction variant = "neutralSolid" >닫기</ DialogAction >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
);
}
DialogTrigger는 Content 밖에 두세요. DialogContent는 기본으로 헤더 닫기 버튼을 표시하며, showCloseButton={false}로 숨길 수 있습니다.
DialogBody는 Content의 최대 높이 안에서 세로로 스크롤합니다. DialogAction은 탭하면 Dialog를 닫지만, disabled 또는 loading 상태에서는 닫지 않습니다.
고유 prop이 없습니다.
title?React.ReactNode
description?React.ReactNode
children?React.ReactNode
container?string | undefined
overlayLevel?1 | 2 | 3 | 4 | undefined
dialogContentProps?Omit < ViewProps, PresenceHandlerKey > | undefined
고유 prop이 없습니다. className, style, children과 padding·gap 같은 스타일 prop을 받습니다.
고유 prop이 없습니다. className, style, children과 padding·gap 같은 스타일 prop을 받습니다.
flexGrow?boolean | Property.FlexGrow | undefined
bleed?BleedValue | undefined
bleedX?BleedValue | undefined
bleedY?BleedValue | undefined
<DialogTrigger>를 탭하면 Dialog가 열립니다. Lynx는 React의 asChild를 지원하지 않으며, Trigger가 자식 요소를 감싸는 native view를 렌더링합니다. Trigger가 버튼 역할과 이름을 노출하고 안쪽 ActionButton은 별도 접근성 요소가 되지 않습니다. 이름은 문자열 children에서 만들며 직접 전달한 accessibility-label이 우선합니다. raw <text> 등에서 텍스트를 파생할 수 없는 경우 이름을 명시하세요.
import "./styles" ;
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { ActionButton } from "@seed-design/lynx-react" ;
export default function Example () {
return (
< DialogRoot >
< DialogTrigger >
< ActionButton variant = "neutralSolid" >Open</ ActionButton >
</ DialogTrigger >
< DialogContent title = "Trigger 패턴" >
< DialogBody >
< text className = "dialog-example-text" >
Trigger를 탭하면 현재 화면 위에 Dialog가 열립니다.
</ text >
</ DialogBody >
< DialogFooter >
< view className = "dialog-example-actions" >
< DialogAction variant = "neutralWeak" >취소</ DialogAction >
< DialogAction variant = "neutralSolid" >확인</ DialogAction >
</ view >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
);
}
Trigger 외의 방식으로 Dialog를 열고 닫으려면 open과 onOpenChange로 상태를 제어합니다.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
} from "@/components/ui/dialog" ;
import { ActionButton, HStack } from "@seed-design/lynx-react" ;
export default function Example () {
const [ open , setOpen ] = useState ( false );
function handleOpen () {
"background only" ;
setOpen ( true );
}
return (
< HStack gap = "x2" wrap = "wrap" justify = "center" >
< ActionButton variant = "neutralSolid" bindtap = {handleOpen}>
열기
</ ActionButton >
< DialogRoot open = {open} onOpenChange = {setOpen}>
< DialogContent title = "제목" description = "설명을 작성할 수 있어요" >
< DialogBody >
< text className = "dialog-example-text" >
Labore do culpa dolore irure nisi dolor dolor laboris veniam ipsum excepteur
adipisicing laboris non quis.
</ text >
</ DialogBody >
< DialogFooter >
< view className = "dialog-example-actions" >
< DialogAction variant = "neutralWeak" >취소</ DialogAction >
< DialogAction variant = "neutralSolid" >확인</ DialogAction >
</ view >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
</ HStack >
);
}
size의 기본값은 "medium"이며 "large"도 지원합니다. 작은 화면에서는 화면 너비에 맞추고, 넓은 화면에서는 size별 최대 너비를 적용합니다. Content 높이도 화면에 맞게 제한됩니다.
import "./styles" ;
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { ActionButton, HStack } from "@seed-design/lynx-react" ;
function DialogExample ({ size } : { size : "medium" | "large" }) {
const isLarge = size === "large" ;
return (
< DialogRoot size = {size}>
< DialogTrigger >
< ActionButton variant = "neutralSolid" >
{isLarge ? "Large Dialog" : "Medium Dialog" }
</ ActionButton >
</ DialogTrigger >
< DialogContent
title = {isLarge ? "Large Dialog" : "Medium Dialog" }
description = {
isLarge
? "넓은 다이얼로그에서 더 많은 상세 콘텐츠를 다룹니다."
: "기본 너비로 상세 정보와 주요 액션을 함께 제공합니다."
}
>
< DialogBody >
< text className = "dialog-example-text" >
{isLarge
? "large size는 넓은 화면에서 더 큰 Dialog token 너비를 사용합니다."
: "medium은 Dialog의 기본 size입니다." }
</ text >
</ DialogBody >
< DialogFooter >
< view className = "dialog-example-actions" >
< DialogAction variant = "neutralWeak" >취소</ DialogAction >
< DialogAction variant = "neutralSolid" >확인</ DialogAction >
</ view >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
);
}
export default function Example () {
return (
< HStack gap = "x2" wrap = "wrap" justify = "center" >
< DialogExample size = "medium" />
< DialogExample size = "large" />
</ HStack >
);
}
DialogBody는 Content의 최대 높이 안에서 세로로 스크롤합니다. Lynx에서는 overflow 상태에 따른 헤더 구분선과 하단 fade mask를 표시하지 않습니다.
import "./styles" ;
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { ActionButton, HStack } from "@seed-design/lynx-react" ;
function DialogExample ({ long } : { long : boolean }) {
return (
< DialogRoot >
< DialogTrigger >
< ActionButton variant = {long ? "neutralSolid" : "neutralWeak" }>
{long ? "긴 본문 (스크롤 적용)" : "짧은 본문 (스크롤 없음)" }
</ ActionButton >
</ DialogTrigger >
< DialogContent
title = {long ? "긴 본문" : "짧은 본문" }
description = {
long
? "본문이 넘치면 DialogBody 안에서 스크롤됩니다"
: "본문이 짧으면 별도 스크롤이 생기지 않습니다"
}
>
< DialogBody >
< view className = "dialog-example-scroll-content" >
{long ? (
Array. from ({ length: 16 }, ( _ , index ) => index + 1 ). map (( line ) => (
< text key = {line} className = "dialog-example-text" >
{line}. Lynx의 DialogBody는 native scroll-view로 렌더링됩니다.
</ text >
))
) : (
< text className = "dialog-example-text" >
내용이 짧으면 마지막 줄까지 바로 확인할 수 있습니다.
</ text >
)}
</ view >
</ DialogBody >
< DialogFooter >
< view className = "dialog-example-actions" >
< DialogAction variant = "neutralWeak" >취소</ DialogAction >
< DialogAction variant = "neutralSolid" >확인</ DialogAction >
</ view >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
);
}
export default function Example () {
return (
< HStack gap = "x2" wrap = "wrap" justify = "center" >
< DialogExample long = { false } />
< DialogExample long />
</ HStack >
);
}
className과 style로 높이와 정렬을 바꿀 수 있습니다. 기본 가로 여백을 없애는 full-bleed 콘텐츠에는 style의 paddingLeft와 paddingRight를 지정하세요.
import "./styles" ;
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { ActionButton, HStack } from "@seed-design/lynx-react" ;
function DialogExample ({ variant } : { variant : "maxHeight" | "minHeight" | "fullBleed" }) {
const isMaxHeight = variant === "maxHeight" ;
const isMinHeight = variant === "minHeight" ;
const isFullBleed = variant === "fullBleed" ;
return (
< DialogRoot >
< DialogTrigger >
< ActionButton variant = "neutralSolid" >
{isMaxHeight ? "maxHeight 200px" : isMinHeight ? "minHeight + 가운데 정렬" : "paddingX 0" }
</ ActionButton >
</ DialogTrigger >
< DialogContent
title = {isMaxHeight ? "본문 최대 높이" : isMinHeight ? "빈 상태" : "Full Bleed" }
description = {
isMaxHeight
? "DialogBody의 높이를 200px로 제한합니다"
: isMinHeight
? "짧은 내용에서도 높이를 고정합니다"
: "가로 패딩을 제거해 콘텐츠를 가장자리까지 배치합니다"
}
>
< DialogBody
className = {
isMaxHeight
? "dialog-example-scroll-body"
: isMinHeight
? "dialog-example-min-height-body"
: undefined
}
minHeight = {isMinHeight ? "240px" : undefined }
style = {isFullBleed ? { paddingLeft: 0 , paddingRight: 0 } : undefined }
>
{isMaxHeight ? (
< view className = "dialog-example-scroll-content" >
{Array. from ({ length: 12 }, ( _ , index ) => index + 1 ). map (( line ) => (
< text key = {line} className = "dialog-example-text" >
{line}. 본문이 200px을 넘으면 그 안에서 스크롤됩니다.
</ text >
))}
</ view >
) : isMinHeight ? (
< text className = "dialog-example-text" >아직 항목이 없습니다</ text >
) : (
< view className = "dialog-example-full-bleed" >
< text className = "dialog-example-text" >가장자리까지 닿는 영역입니다</ text >
</ view >
)}
</ DialogBody >
< DialogFooter >
< view className = "dialog-example-actions" >
< DialogAction variant = "neutralWeak" >취소</ DialogAction >
< DialogAction variant = "neutralSolid" >확인</ DialogAction >
</ view >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
);
}
export default function Example () {
return (
< HStack gap = "x2" wrap = "wrap" justify = "center" >
< DialogExample variant = "maxHeight" />
< DialogExample variant = "minHeight" />
< DialogExample variant = "fullBleed" />
</ HStack >
);
}
본문이 최대 높이에 닿으면 DialogBody만 스크롤되고 Header와 Footer는 그대로 보입니다. 최대 높이는 화면 높이의 80%와, 위아래 inset 중 큰 값을 양쪽에서 뺀 높이 중 작은 쪽입니다.
import "./styles" ;
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { ActionButton } from "@seed-design/lynx-react" ;
export default function Example () {
return (
< DialogRoot >
< DialogTrigger >
< ActionButton variant = "neutralSolid" >Open Dialog</ ActionButton >
</ DialogTrigger >
< DialogContent title = "긴 본문" description = "최대 높이에 닿으면 Body만 스크롤됩니다" >
< DialogBody >
< view className = "dialog-example-scroll-content" >
{Array. from ({ length: 40 }, ( _ , index ) => index + 1 ). map (( line ) => (
< text key = {line} className = "dialog-example-text" >
{line}. 본문이 길어지면 Body 영역만 스크롤됩니다.
</ text >
))}
</ view >
</ DialogBody >
< DialogFooter >
< view className = "dialog-example-actions" >
< DialogAction variant = "neutralWeak" >취소</ DialogAction >
< DialogAction variant = "neutralSolid" >확인</ DialogAction >
</ view >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
);
}
showCloseButton={false}로 헤더 닫기 버튼을 숨길 수 있습니다. 이 경우 푸터 등에 닫기 action을 제공하세요.
import "./styles" ;
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { ActionButton, HStack } from "@seed-design/lynx-react" ;
function DialogExample ({ showCloseAction } : { showCloseAction : boolean }) {
return (
< DialogRoot >
< DialogTrigger >
< ActionButton variant = "neutralSolid" >
{showCloseAction ? "닫기 액션 있음" : "닫기 액션 없음" }
</ ActionButton >
</ DialogTrigger >
< DialogContent
title = {showCloseAction ? "닫기 액션" : "닫기 액션 없음" }
description = {
showCloseAction
? "Registry DialogContent가 닫기 ActionButton을 내부에서 제공합니다."
: "닫기 액션을 숨긴 경우 푸터에 닫기 액션을 제공해야 합니다."
}
showCloseButton = {showCloseAction}
>
< DialogBody >
< text className = "dialog-example-text" >
{showCloseAction
? "DialogContent의 showCloseButton을 사용합니다."
: "showCloseButton={false}인 경우 푸터 액션만 제공합니다." }
</ text >
</ DialogBody >
< DialogFooter >
< view className = "dialog-example-actions" >
< DialogAction variant = "neutralWeak" >취소</ DialogAction >
< DialogAction variant = "neutralSolid" >확인</ DialogAction >
</ view >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
);
}
export default function Example () {
return (
< HStack gap = "x2" wrap = "wrap" justify = "center" >
< DialogExample showCloseAction />
< DialogExample showCloseAction = { false } />
</ HStack >
);
}
DialogFooter는 flex 레이아웃만 제공합니다. 버튼 배치는 자식 view에 flex-direction, justify-content, gap 등을 지정해 직접 구성합니다.
import "./styles" ;
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { ActionButton } from "@seed-design/lynx-react" ;
export default function Example () {
return (
< DialogRoot >
< DialogTrigger >
< ActionButton variant = "neutralSolid" >Footer 레이아웃</ ActionButton >
</ DialogTrigger >
< DialogContent
title = "Footer 레이아웃"
description = "버튼 배치는 view의 flex 레이아웃으로 직접 구성합니다."
>
< DialogBody >
< view className = "dialog-example-column" >
< text className = "dialog-example-text" >DialogFooter는 flex 레이아웃만 제공합니다.</ text >
< text className = "dialog-example-text" >
넓은 다이얼로그에서는 주요 액션을 우측에 가로로 정렬할 수 있습니다.
</ text >
</ view >
</ DialogBody >
< DialogFooter >
< view className = "dialog-example-actions" >
< DialogAction variant = "neutralWeak" >취소</ DialogAction >
< DialogAction variant = "neutralSolid" >확인</ DialogAction >
</ view >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
);
}
Lynx의 DialogAction에는 React 이벤트의 preventDefault()를 사용하는 방식이 없습니다. Dialog를 controlled 상태로 만들고 onOpenChange(false)를 조건에 따라 무시하면 닫힘을 막을 수 있습니다.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { ActionButton } from "@seed-design/lynx-react" ;
export default function Example () {
const [ open , setOpen ] = useState ( false );
const [ preventClose , setPreventClose ] = useState ( true );
function handleTogglePreventClose () {
"background only" ;
setPreventClose (( previous ) => ! previous);
}
function handleOpenChange ( nextOpen : boolean ) {
if (nextOpen || ! preventClose) {
setOpen (nextOpen);
}
}
return (
< DialogRoot open = {open} onOpenChange = {handleOpenChange}>
< DialogTrigger >
< ActionButton variant = "neutralSolid" >열기</ ActionButton >
</ DialogTrigger >
< DialogContent
title = "닫기 방지"
description = "확인 버튼을 눌러도 Dialog가 닫히지 않도록 설정할 수 있습니다."
>
< DialogBody >
< view className = "dialog-example-option" >
< text className = "dialog-example-text" >닫힘 방지: { JSON . stringify (preventClose)}</ text >
< ActionButton variant = "neutralWeak" bindtap = {handleTogglePreventClose}>
전환
</ ActionButton >
</ view >
</ DialogBody >
< DialogFooter >
< view className = "dialog-example-actions" >
< DialogAction variant = "neutralWeak" >취소</ DialogAction >
< DialogAction variant = "neutralSolid" >확인</ DialogAction >
</ view >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
);
}
Lynx의 onOpenChange는 변경된 open 값만 전달합니다. React 버전의 두 번째 인자인 details.reason은 지원하지 않습니다. 닫힘 원인이 필요하면 앱이 소유한 버튼과 Trigger의 이벤트 핸들러에서 원인을 별도 상태로 기록하세요.
React 예제처럼 closeButton, escapeKeyDown, interactOutside별로 확인 Dialog를 띄우는 동작은 Lynx에서 지원하지 않습니다. Lynx의 callback만으로는 닫힘 원인을 구분할 수 없으므로, 확인이 필요한 액션은 앱이 소유한 버튼의 핸들러에서 확인 Dialog를 먼저 열고 원본 Dialog의 open을 직접 제어하세요.
container를 지정하지 않으면 Dialog는 Lynx view 안에 렌더링됩니다. container="window"처럼 native container 이름을 지정하면 host 화면까지 덮는 native overlay에 렌더링됩니다. overlayLevel은 overlay의 표시 순서를 정합니다.
import "./styles" ;
import {
DialogAction,
DialogBody,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog" ;
import { ActionButton } from "@seed-design/lynx-react" ;
export default function Example () {
return (
< DialogRoot >
< DialogTrigger >
< ActionButton variant = "neutralSolid" >열기</ ActionButton >
</ DialogTrigger >
< DialogContent
container = "window"
overlayLevel = { 2 }
title = "Overlay"
description = "Lynx에서는 Positioner의 container와 overlayLevel로 네이티브 overlay 레이어를 선택합니다."
>
< DialogBody >
< text className = "dialog-example-text" >
콘텐츠는 window 컨테이너와 overlay level 2 위에 표시됩니다.
</ text >
</ DialogBody >
< DialogFooter >
< view className = "dialog-example-actions" >
< DialogAction variant = "neutralWeak" >취소</ DialogAction >
< DialogAction variant = "neutralSolid" >확인</ DialogAction >
</ view >
</ DialogFooter >
</ DialogContent >
</ DialogRoot >
);
}
React의 ResponsiveDialog와 같은 자동 전환 컴포넌트는 Lynx에서 제공하지 않습니다. 화면 크기에 따라 Dialog와 BottomSheet를 앱에서 직접 선택하거나, 동일한 controlled 상태를 두 컴포넌트에 연결하세요.
Trigger는 자식을 native view로 감싸며 asChild를 제공하지 않습니다.
onOpenChange는 닫힌 원인 없이 boolean 값만 전달합니다.
DialogBody는 native scroll view로 렌더링하며, overflow 구분선과 fade mask를 표시하지 않습니다.
제목에는 heading 접근성을 적용하지만 Content와 제목을 DOM id로 연결하지 않습니다.
container와 overlayLevel로 native overlay의 위치와 표시 순서를 지정합니다.
ResponsiveDialog, lazyMount, unmountOnExit은 제공하지 않습니다. 반응형 전환이 필요하면 같은 controlled 상태로 Dialog와 Bottom Sheet를 선택하세요.