Menu
사용자가 취할 수 있는 선택지나 액션 리스트를 제공하는 컴포넌트입니다.
<overlay>import "./styles";
import IconPencilLine from "@karrotmarket/lynx-monochrome-icon/IconPencilLine";
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import IconTrashcanLine from "@karrotmarket/lynx-monochrome-icon/IconTrashcanLine";
import { ActionButton, VStack, useSeedClassName } from "@seed-design/lynx-react";
import {
MenuContent,
MenuGroup,
MenuGroupLabel,
MenuItem,
MenuRoot,
MenuTrigger,
} from "@/components/ui/menu";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
<view className={`${seedClassName} docs-lynx-menu-root`}>
<VStack width="full" height="full" align="center" justify="center">
<MenuRoot>
<MenuTrigger>
<ActionButton variant="neutralSolid">열기</ActionButton>
</MenuTrigger>
<MenuContent>
<MenuGroup>
<MenuGroupLabel>작업</MenuGroupLabel>
<MenuItem label="라이브러리에 추가" prefixIcon={<IconPlusLine />} />
<MenuItem
label="수정"
description="현재 항목을 수정합니다"
prefixIcon={<IconPencilLine />}
/>
</MenuGroup>
<MenuGroup>
<MenuItem
label="삭제"
description="이 작업은 되돌릴 수 없습니다"
tone="critical"
prefixIcon={<IconTrashcanLine />}
/>
</MenuGroup>
</MenuContent>
</MenuRoot>
</VStack>
</view>
);
}Installation
npx @seed-design/cli@latest add ui:menupnpm dlx @seed-design/cli@latest add ui:menuyarn dlx @seed-design/cli@latest add ui:menubun x @seed-design/cli@latest add ui:menu의존성 설치
npm install @seed-design/lynx-reactyarn add @seed-design/lynx-reactpnpm add @seed-design/lynx-reactbun add @seed-design/lynx-react아래 코드를 복사 후 붙여넣고 사용하세요
/**
* @file ui:menu
* @requires @seed-design/lynx-react@>=0.7.0 <1.0.0
* @requires @seed-design/lynx-css@>=0.11.0 <1.0.0
**/
import * as React from "@lynx-js/react";
import { Menu as SeedMenu, type LynxIconElementProps } from "@seed-design/lynx-react";
export interface MenuRootProps extends SeedMenu.RootProps {}
/**
* @see https://seed-design.io/lynx/components/menu
*/
export const MenuRoot = SeedMenu.Root;
export interface MenuAnchorProps extends SeedMenu.AnchorProps {}
/**
* 위치 기준점만 만드는 Anchor입니다. 탭으로 메뉴를 열고 닫으려면 MenuTrigger를 사용하세요.
*
* @see https://seed-design.io/lynx/components/menu
*/
export const MenuAnchor = SeedMenu.Anchor;
export interface MenuTriggerProps extends SeedMenu.TriggerProps {}
/**
* @see https://seed-design.io/lynx/components/menu
*/
export const MenuTrigger = SeedMenu.Trigger;
export interface MenuContentProps extends SeedMenu.ContentProps {}
/**
* Overlay, 위치 계산, 표시 수명과 긴 메뉴의 스크롤 영역을 함께 구성합니다.
* 자식에 별도 Positioner나 ScrollArea를 추가하지 마세요.
*
* @see https://seed-design.io/lynx/components/menu
*/
export const MenuContent = SeedMenu.Content;
export interface MenuGroupProps extends SeedMenu.GroupProps {}
export const MenuGroup = SeedMenu.Group;
export interface MenuGroupLabelProps extends SeedMenu.GroupLabelProps {}
export const MenuGroupLabel = SeedMenu.GroupLabel;
export interface MenuItemProps extends Omit<SeedMenu.ItemProps, "children"> {
label: React.ReactNode;
description?: React.ReactNode;
prefixIcon?: React.ReactElement<LynxIconElementProps>;
suffixIcon?: React.ReactElement<LynxIconElementProps>;
}
/**
* 아이콘, 레이블, 설명 슬롯을 조립해 한 항목으로 제공합니다. `bindtap`은 선택 직전에
* 호출되고, 비활성 항목에는 호출되지 않습니다.
*
* @see https://seed-design.io/lynx/components/menu
*/
export const MenuItem = React.forwardRef<unknown, MenuItemProps>(
(
{
label,
description,
prefixIcon,
suffixIcon,
"accessibility-label": accessibilityLabel,
...otherProps
},
ref,
) => {
return (
<SeedMenu.Item
ref={ref}
accessibility-label={accessibilityLabel ?? (typeof label === "string" ? label : undefined)}
{...otherProps}
>
{prefixIcon ? <SeedMenu.PrefixIcon icon={prefixIcon} /> : null}
<SeedMenu.ItemBody>
<SeedMenu.ItemLabel>{label}</SeedMenu.ItemLabel>
{description != null ? (
<SeedMenu.ItemDescription>{description}</SeedMenu.ItemDescription>
) : null}
</SeedMenu.ItemBody>
{suffixIcon ? <SeedMenu.SuffixIcon icon={suffixIcon} /> : null}
</SeedMenu.Item>
);
},
);
MenuItem.displayName = "MenuItem";
/**
* 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.
*/
Usage
Menu는 Root, Trigger, Content와 Group으로 구성합니다. MenuContent는 native overlay, 위치 계산, 표시 수명, 긴 목록의 세로 스크롤을 함께 처리합니다.
import { ActionButton } from "@seed-design/lynx-react";
import {
MenuContent,
MenuGroup,
MenuGroupLabel,
MenuItem,
MenuRoot,
MenuTrigger,
} from "@/components/ui/menu";
export function App() {
return (
<MenuRoot>
<MenuTrigger>
<ActionButton variant="neutralSolid">열기</ActionButton>
</MenuTrigger>
<MenuContent>
<MenuGroup>
<MenuGroupLabel>작업</MenuGroupLabel>
<MenuItem label="항목 1" />
<MenuItem label="항목 2" />
</MenuGroup>
<MenuGroup>
<MenuItem label="항목 3" />
</MenuGroup>
</MenuContent>
</MenuRoot>
);
}MenuRoot는 열림 상태와 위치를 관리합니다.MenuTrigger는 닫힌 Menu를 탭으로 엽니다.MenuAnchor는 위치 기준점만 제공합니다. 열림 상태는open과onOpenChange로 제어합니다.MenuContent는 overlay와 스크롤 가능한 메뉴 목록을 렌더링합니다. 자식에 별도Positioner나ScrollArea를 추가하지 않습니다.MenuGroup과MenuGroupLabel은 관련된 항목을 묶고 제목을 표시합니다.MenuItem은label, 선택적description,prefixIcon,suffixIcon을 한 항목으로 조립합니다.
Props
MenuRoot
Prop
Type
open?boolean | undefineddefaultOpen?boolean | undefinedonOpenChange?((open: boolean, details: MenuOpenChangeDetails) => void) | undefineddisabled?boolean | undefinedplacement?Placement | undefinedgutter?number | undefinedoverflowPadding?number | undefinedmatchReferenceWidth?boolean | undefinedsize?"small" | "medium" | "responsive" | undefinedstyle?CSSProperties | undefinedchildren?React.ReactNodeclassName?string | undefinedMenuTrigger
Prop
Type
disabled?boolean | undefinedstyle?CSSProperties | undefinedchildren?React.ReactNodeclassName?string | undefinedbindtap?EventHandler<BaseTouchEvent<Target>> | undefinedmain-thread:bindtap?EventHandler<BaseTouchEvent<Element>> | undefinedMenuAnchor
Prop
Type
style?CSSProperties | undefinedchildren?React.ReactNodeclassName?string | undefinedMenuContent
Prop
Type
style?CSSProperties | undefinedchildren?React.ReactNodeclassName?string | undefinedMenuGroup
Prop
Type
style?CSSProperties | undefinedchildren?React.ReactNodeclassName?string | undefinedMenuGroupLabel
Prop
Type
style?CSSProperties | undefinedchildren?React.ReactNodeclassName?string | undefinedMenuItem
Prop
Type
labelReact.ReactNodedescription?React.ReactNodeprefixIcon?React.ReactElement<LynxIconElementProps, string | React.JSXElementConstructor<any>> | undefinedsuffixIcon?React.ReactElement<LynxIconElementProps, string | React.JSXElementConstructor<any>> | undefinedclassName?string | undefinedbindtap?EventHandler<BaseTouchEvent<Target>> | undefinedmain-thread:bindtap?EventHandler<BaseTouchEvent<Element>> | undefineddisabled?boolean | undefinedstyle?CSSProperties | undefinedExamples
Trigger
MenuTrigger를 탭하면 닫힌 Menu가 열립니다. MenuItem을 탭하거나 바깥 영역을 탭하면 닫힙니다.
import "./styles";
import IconPencilLine from "@karrotmarket/lynx-monochrome-icon/IconPencilLine";
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import IconTrashcanLine from "@karrotmarket/lynx-monochrome-icon/IconTrashcanLine";
import { ActionButton, VStack, useSeedClassName } from "@seed-design/lynx-react";
import {
MenuContent,
MenuGroup,
MenuGroupLabel,
MenuItem,
MenuRoot,
MenuTrigger,
} from "@/components/ui/menu";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
<view className={`${seedClassName} docs-lynx-menu-root`}>
<VStack width="full" height="full" align="center" justify="center">
<MenuRoot>
<MenuTrigger>
<ActionButton variant="neutralSolid">열기</ActionButton>
</MenuTrigger>
<MenuContent>
<MenuGroup>
<MenuGroupLabel>작업</MenuGroupLabel>
<MenuItem label="라이브러리에 추가" prefixIcon={<IconPlusLine />} />
<MenuItem
label="수정"
description="현재 항목을 수정합니다"
prefixIcon={<IconPencilLine />}
/>
</MenuGroup>
<MenuGroup>
<MenuItem
label="삭제"
description="이 작업은 되돌릴 수 없습니다"
tone="critical"
prefixIcon={<IconTrashcanLine />}
/>
</MenuGroup>
</MenuContent>
</MenuRoot>
</VStack>
</view>
);
}Size
size로 Menu의 크기를 정합니다. 기본값은 "medium"입니다. "responsive"는 현재 화면 너비를 기준으로 "small" 또는 "medium"으로 바뀝니다.
import "./styles";
import IconPencilLine from "@karrotmarket/lynx-monochrome-icon/IconPencilLine";
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import { ActionButton, HStack, useSeedClassName } from "@seed-design/lynx-react";
import {
MenuContent,
MenuGroup,
MenuGroupLabel,
MenuItem,
MenuRoot,
MenuTrigger,
type MenuRootProps,
} from "@/components/ui/menu";
function SizeMenu({ size, label }: { size: MenuRootProps["size"]; label: string }) {
return (
<MenuRoot size={size}>
<MenuTrigger>
<ActionButton variant="neutralSolid">{label}</ActionButton>
</MenuTrigger>
<MenuContent>
<MenuGroup>
<MenuGroupLabel>작업</MenuGroupLabel>
<MenuItem label="추가" prefixIcon={<IconPlusLine />} />
<MenuItem label="수정" prefixIcon={<IconPencilLine />} />
</MenuGroup>
</MenuContent>
</MenuRoot>
);
}
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
<view className={`${seedClassName} docs-lynx-menu-root`}>
<HStack width="full" height="full" gap="x4" align="center" justify="center">
<SizeMenu size="medium" label="Medium" />
<SizeMenu size="small" label="Small" />
<SizeMenu size="responsive" label="Responsive" />
</HStack>
</view>
);
}With Description
MenuItem의 description에 항목의 부가 설명을 전달합니다.
import "./styles";
import IconArrowUpBracketDownLine from "@karrotmarket/lynx-monochrome-icon/IconArrowUpBracketDownLine";
import IconPencilLine from "@karrotmarket/lynx-monochrome-icon/IconPencilLine";
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import { ActionButton, VStack, useSeedClassName } from "@seed-design/lynx-react";
import { MenuContent, MenuGroup, MenuItem, MenuRoot, MenuTrigger } from "@/components/ui/menu";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
<view className={`${seedClassName} docs-lynx-menu-root`}>
<VStack width="full" height="full" align="center" justify="center">
<MenuRoot>
<MenuTrigger>
<ActionButton variant="neutralSolid">열기</ActionButton>
</MenuTrigger>
<MenuContent>
<MenuGroup>
<MenuItem
label="라이브러리에 추가"
description="내 라이브러리에 항목을 추가합니다"
prefixIcon={<IconPlusLine />}
/>
<MenuItem
label="수정"
description="현재 항목을 수정합니다"
prefixIcon={<IconPencilLine />}
/>
<MenuItem
label="공유"
description="다른 사람에게 공유합니다"
prefixIcon={<IconArrowUpBracketDownLine />}
/>
</MenuGroup>
</MenuContent>
</MenuRoot>
</VStack>
</view>
);
}Tone
MenuItem의 tone="critical"로 삭제처럼 주의가 필요한 액션을 표시합니다.
import "./styles";
import IconPencilLine from "@karrotmarket/lynx-monochrome-icon/IconPencilLine";
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import IconTrashcanLine from "@karrotmarket/lynx-monochrome-icon/IconTrashcanLine";
import { ActionButton, VStack, useSeedClassName } from "@seed-design/lynx-react";
import { MenuContent, MenuGroup, MenuItem, MenuRoot, MenuTrigger } from "@/components/ui/menu";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
<view className={`${seedClassName} docs-lynx-menu-root`}>
<VStack width="full" height="full" align="center" justify="center">
<MenuRoot>
<MenuTrigger>
<ActionButton variant="neutralSolid">열기</ActionButton>
</MenuTrigger>
<MenuContent>
<MenuGroup>
<MenuItem label="추가" prefixIcon={<IconPlusLine />} />
<MenuItem label="수정" prefixIcon={<IconPencilLine />} />
</MenuGroup>
<MenuGroup>
<MenuItem label="삭제" tone="critical" prefixIcon={<IconTrashcanLine />} />
</MenuGroup>
</MenuContent>
</MenuRoot>
</VStack>
</view>
);
}Disabled Items
disabled 항목은 탭해도 bindtap이 실행되지 않고 Menu를 닫지 않습니다.
import "./styles";
import IconArrowUpBracketDownLine from "@karrotmarket/lynx-monochrome-icon/IconArrowUpBracketDownLine";
import IconPencilLine from "@karrotmarket/lynx-monochrome-icon/IconPencilLine";
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import { ActionButton, VStack, useSeedClassName } from "@seed-design/lynx-react";
import { MenuContent, MenuGroup, MenuItem, MenuRoot, MenuTrigger } from "@/components/ui/menu";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
<view className={`${seedClassName} docs-lynx-menu-root`}>
<VStack width="full" height="full" align="center" justify="center">
<MenuRoot>
<MenuTrigger>
<ActionButton variant="neutralSolid">열기</ActionButton>
</MenuTrigger>
<MenuContent>
<MenuGroup>
<MenuItem label="추가" prefixIcon={<IconPlusLine />} />
<MenuItem
label="수정"
description="현재 항목을 수정합니다"
prefixIcon={<IconPencilLine />}
disabled
/>
<MenuItem label="공유" prefixIcon={<IconArrowUpBracketDownLine />} />
</MenuGroup>
</MenuContent>
</MenuRoot>
</VStack>
</view>
);
}Placement
MenuRoot의 placement로 Menu를 기준 요소의 12개 방향에 배치합니다. 기본값은 "bottom"입니다. 화면 가장자리에서 공간이 부족하면 native runtime이 반대쪽으로 뒤집거나 경계 안으로 이동합니다.
import "./styles";
import IconPencilLine from "@karrotmarket/lynx-monochrome-icon/IconPencilLine";
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import { ActionButton, Box, HStack, VStack, useSeedClassName } from "@seed-design/lynx-react";
import {
MenuContent,
MenuGroup,
MenuItem,
MenuRoot,
MenuTrigger,
type MenuRootProps,
} from "@/components/ui/menu";
function PlacementMenu({ placement }: { placement: NonNullable<MenuRootProps["placement"]> }) {
return (
<Box width="200px">
<MenuRoot placement={placement}>
<MenuTrigger>
<ActionButton variant="neutralSolid">{placement}</ActionButton>
</MenuTrigger>
<MenuContent>
<MenuGroup>
<MenuItem label="추가" prefixIcon={<IconPlusLine />} />
<MenuItem label="수정" prefixIcon={<IconPencilLine />} />
</MenuGroup>
</MenuContent>
</MenuRoot>
</Box>
);
}
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
<view className={`${seedClassName} docs-lynx-menu-root`}>
<scroll-view scroll-orientation="horizontal" style={{ width: "100%", height: "100%" }}>
<VStack width="760px" gap="x10" px="x10" py="x10">
<HStack gap="x10">
<PlacementMenu placement="top-end" />
<PlacementMenu placement="top" />
<PlacementMenu placement="top-start" />
</HStack>
<HStack gap="x10">
<PlacementMenu placement="left-end" />
<Box width="200px" />
<PlacementMenu placement="right-end" />
</HStack>
<HStack gap="x10">
<PlacementMenu placement="left" />
<Box width="200px" />
<PlacementMenu placement="right" />
</HStack>
<HStack gap="x10">
<PlacementMenu placement="left-start" />
<Box width="200px" />
<PlacementMenu placement="right-start" />
</HStack>
<HStack gap="x10">
<PlacementMenu placement="bottom-end" />
<PlacementMenu placement="bottom" />
<PlacementMenu placement="bottom-start" />
</HStack>
</VStack>
</scroll-view>
</view>
);
}Anchor
MenuAnchor는 Menu 위치만 정하고 탭으로 열고 닫지는 않습니다. 이 예제처럼 open과 onOpenChange로 상태를 제어할 수 있습니다.
import "./styles";
import IconPencilLine from "@karrotmarket/lynx-monochrome-icon/IconPencilLine";
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import { useState } from "@lynx-js/react";
import { Box, HStack, useSeedClassName } from "@seed-design/lynx-react";
import { MenuAnchor, MenuContent, MenuGroup, MenuItem, MenuRoot } from "@/components/ui/menu";
import { Switch } from "@/components/ui/switch";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
const [open, setOpen] = useState(false);
function handleOpenChange(nextOpen: boolean, details?: { reason?: string }) {
"background only";
if (!nextOpen && details?.reason === "interactOutside") return;
setOpen(nextOpen);
}
return (
<view className={`${seedClassName} docs-lynx-menu-root`}>
<HStack width="full" height="full" px="x5" align="center" justify="space-between">
<Switch tone="neutral" label="메뉴" checked={open} onCheckedChange={setOpen} />
<MenuRoot open={open} onOpenChange={handleOpenChange}>
<MenuAnchor>
<Box
width="80px"
height="80px"
overflowX="hidden"
overflowY="hidden"
borderRadius="full"
>
<image
src="https://avatars.githubusercontent.com/u/54893898?v=4"
mode="aspectFill"
style={{ width: "80px", height: "80px" }}
/>
</Box>
</MenuAnchor>
<MenuContent>
<MenuGroup>
<MenuItem label="추가" prefixIcon={<IconPlusLine />} />
<MenuItem label="수정" prefixIcon={<IconPencilLine />} />
</MenuGroup>
</MenuContent>
</MenuRoot>
</HStack>
</view>
);
}Native overlay가 열려 있는 동안에는 Anchor 바깥의 Switch를 탭할 수 없습니다. 이 예제는 Menu가 닫힌 상태에서 Switch로 열고, 항목을 선택해 닫는 흐름을 보여줍니다. overlay 바깥 탭을 무시하는 제어는 onOpenChange에서 details.reason === "interactOutside"를 걸러 구현합니다.
Match Width
matchReferenceWidth를 사용하면 Menu 너비가 Trigger 또는 Anchor 너비와 같아집니다.
import "./styles";
import { ActionButton, Box, VStack, useSeedClassName } from "@seed-design/lynx-react";
import { MenuContent, MenuGroup, MenuItem, MenuRoot, MenuTrigger } from "@/components/ui/menu";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
return (
<view className={`${seedClassName} docs-lynx-menu-root`}>
<VStack width="full" height="full" align="center" justify="center">
<MenuRoot matchReferenceWidth>
<MenuTrigger>
<Box width="400px" maxWidth="100%">
<ActionButton variant="neutralSolid">열기</ActionButton>
</Box>
</MenuTrigger>
<MenuContent>
<MenuGroup>
<MenuItem label="추가" />
<MenuItem label="수정" />
<MenuItem label="공유" />
</MenuGroup>
</MenuContent>
</MenuRoot>
</VStack>
</view>
);
}onOpenChange details
onOpenChange의 두 번째 인자인 details에는 상태를 바꾼 이유와 native event가 들어옵니다.
- 열림:
"trigger" - 닫힘:
"trigger","interactOutside","itemClick" - native overlay가 닫힘을 요청한 경우:
"dismiss"
import "./styles";
import IconPencilLine from "@karrotmarket/lynx-monochrome-icon/IconPencilLine";
import IconPlusLine from "@karrotmarket/lynx-monochrome-icon/IconPlusLine";
import { useState } from "@lynx-js/react";
import { ActionButton, HStack, VStack, useSeedClassName } from "@seed-design/lynx-react";
import { MenuContent, MenuGroup, MenuItem, MenuRoot, MenuTrigger } from "@/components/ui/menu";
export default function Example() {
const seedClassName = useSeedClassName({ colorMode: "system" });
const [open, setOpen] = useState(false);
const [openReason, setOpenReason] = useState<string | null>(null);
const [closeReason, setCloseReason] = useState<string | null>(null);
function handleOpenChange(nextOpen: boolean, details?: { reason?: string }) {
"background only";
setOpen(nextOpen);
(nextOpen ? setOpenReason : setCloseReason)(details?.reason ?? null);
}
return (
<view className={`${seedClassName} docs-lynx-menu-root`}>
<VStack width="full" height="full" gap="x4" align="center" justify="center">
<MenuRoot open={open} onOpenChange={handleOpenChange}>
<MenuTrigger>
<ActionButton variant="neutralSolid">열기</ActionButton>
</MenuTrigger>
<MenuContent>
<MenuGroup>
<MenuItem label="추가" prefixIcon={<IconPlusLine />} />
<MenuItem label="수정" prefixIcon={<IconPencilLine />} />
</MenuGroup>
</MenuContent>
</MenuRoot>
<HStack gap="x4">
<text>마지막 열림 이유: {openReason ?? "-"}</text>
<text>마지막 닫힘 이유: {closeReason ?? "-"}</text>
</HStack>
</VStack>
</view>
);
}웹 버전과의 차이
Lynx Menu는 native overlay 위에 렌더링합니다. HTML DOM, asChild, 키보드 포커스, typeahead, ESC 키 닫힘은 지원하지 않습니다. 따라서 escapeKeyDown과 cascadeDismiss reason도 제공하지 않습니다. 화면과 앱 수준에서 필요한 키보드 접근성은 host의 native 접근성 흐름으로 확인하세요.
| 항목 | 웹 | Lynx |
|---|---|---|
| Trigger 조합 | asChild 지원 | 자식을 감싸는 native Trigger를 사용 |
| 위치와 목록 | DOM positioner와 scroll area | MenuContent가 native overlay, 위치, 스크롤을 함께 처리 |
| 바깥 상호작용 | DOM pointer와 키보드 | 바깥 탭은 interactOutside, native dismissal은 dismiss |
| 키보드 | ESC, focus, typeahead 지원 | 미지원 |
| Anchor가 열린 동안의 제어 | 바깥 제어를 계속 조합 가능 | fullscreen overlay가 Anchor 밖의 탭을 가림 |
Last updated on