# Menu URL: /react/components/menu Source: https://github.com/daangn/seed-design/blob/dev/docs/content/react/components/menu.mdx 사용자가 취할 수 있는 선택지나 액션 리스트를 제공하는 컴포넌트입니다. 사용 가능 버전: @seed-design/react@2.0.0, @seed-design/css@2.0.0 ## Preview ```tsx import { IconPencilLine, IconPlusLine, IconTrashcanLine, } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { MenuContent, MenuGroup, MenuGroupLabel, MenuItem, MenuRoot, MenuTrigger, } from "seed-design/ui/menu"; export default function MenuPreview() { return ( 열기 작업 } /> } /> } /> ); } ``` ## Installation - npm: npx @seed-design/cli@latest add ui:menu - pnpm: pnpm dlx @seed-design/cli@latest add ui:menu - yarn: yarn dlx @seed-design/cli@latest add ui:menu - bun: bun x @seed-design/cli@latest add ui:menu ## Usage Menu는 아래와 같은 구조로 구성됩니다. ```tsx import { MenuRoot, MenuTrigger, MenuContent, MenuGroup, MenuGroupLabel, MenuItem, } from "seed-design/ui/menu"; ``` ```tsx ... 그룹 제목 ``` - `MenuRoot`: 메뉴의 상태(열림/닫힘)와 위치를 관리합니다. - `MenuTrigger`: 클릭 시 메뉴를 열고 닫는 트리거입니다. - `MenuAnchor`: 메뉴의 위치 기준점만 제공하며, 열고 닫는 동작은 포함하지 않습니다. 트리거 동작을 직접 제어해야 하는 경우에 `MenuTrigger` 대신 사용합니다. - `MenuContent`: 메뉴 항목들을 감싸는 플로팅 컨테이너입니다. - `MenuGroup`: 관련된 항목들을 그룹으로 묶습니다. 모든 `MenuItem`은 `MenuGroup` 안에 있어야 합니다. - `MenuGroupLabel`: 그룹의 제목을 표시합니다. - `MenuItem`: 개별 메뉴 항목입니다. ## Props ### `MenuRoot` ### `MenuTrigger` ### `MenuAnchor` ### `MenuContent` ### `MenuGroup` ### `MenuGroupLabel` ### `MenuItem` ## Examples ### Trigger ``는 `aria-haspopup="menu"` 속성을 설정하고, Menu의 `open` 상태에 따라 `aria-expanded` 속성을 자동으로 설정합니다. 이 속성은 스크린 리더와 같은 보조 기술에 유용합니다. ## Preview ```tsx import { IconPencilLine, IconPlusLine, IconTrashcanLine, } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { MenuContent, MenuGroup, MenuGroupLabel, MenuItem, MenuRoot, MenuTrigger, } from "seed-design/ui/menu"; export default function MenuPreview() { return ( 열기 작업 } /> } /> } /> ); } ``` ### Size `size`로 MenuRoot의 크기를 정합니다. (default: `medium`) `responsive`는 화면 너비에 따라 size가 자동으로 전환되는 값입니다. 여러 화면 너비를 함께 지원하는 제품에서 `size=responsive`를 사용하여 대응합니다. ```tsx import { IconPencilLine, IconPlusLine } from "@karrotmarket/react-monochrome-icon"; import { HStack } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { MenuContent, MenuGroup, MenuGroupLabel, MenuItem, MenuRoot, MenuTrigger, } from "seed-design/ui/menu"; export default function MenuSize() { return ( Medium 작업 } /> } /> Small 작업 } /> } /> Responsive 작업 } /> } /> ); } ``` ### With Description `MenuItem`의 `description` prop을 사용하여 항목에 부가 설명을 추가합니다. ```tsx import { IconArrowUpBracketDownLine, IconPencilLine, IconPlusLine, } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { MenuContent, MenuGroup, MenuItem, MenuRoot, MenuTrigger } from "seed-design/ui/menu"; export default function MenuWithDescription() { return ( 열기 } /> } /> } /> ); } ``` ### Tone `MenuItem`의 `tone` prop으로 항목의 톤을 설정합니다. ```tsx import { IconPencilLine, IconPlusLine, IconTrashcanLine, } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { MenuContent, MenuGroup, MenuItem, MenuRoot, MenuTrigger } from "seed-design/ui/menu"; export default function MenuTone() { return ( 열기 } /> } /> } /> ); } ``` ### Disabled Items `MenuItem`의 `disabled` prop을 사용하여 특정 항목을 비활성화합니다. ```tsx import { IconArrowUpBracketDownLine, IconPencilLine, IconPlusLine, } from "@karrotmarket/react-monochrome-icon"; import { ActionButton } from "seed-design/ui/action-button"; import { MenuContent, MenuGroup, MenuItem, MenuRoot, MenuTrigger } from "seed-design/ui/menu"; export default function MenuDisabled() { return ( 열기 } /> } disabled /> } /> ); } ``` ### Placement `MenuRoot`의 `placement` prop으로 메뉴의 위치를 설정합니다. 기본값은 `"bottom"`입니다. ```tsx import { IconPencilLine, IconPlusLine } from "@karrotmarket/react-monochrome-icon"; import { Box } from "@seed-design/react"; import { ActionButton } from "seed-design/ui/action-button"; import { MenuContent, MenuGroup, MenuItem, MenuRoot, MenuTrigger, type MenuRootProps, } from "seed-design/ui/menu"; function PlacementMenu({ placement }: { placement: NonNullable }) { return ( {placement} } /> } /> ); } export default function MenuPlacement() { return (
); } ``` ### Anchor `MenuAnchor`의 `children`은 Menu가 위치를 잡는 데에만 사용되며, `MenuTrigger`와 달리 클릭으로 열고 닫는 동작이 포함되지 않습니다. `open` prop을 controlled하게 사용하여 열리고 닫힌 상태를 직접 관리해야 합니다. 아래 예시의 경우 `onOpenChange` 콜백에 조건을 추가하여 바깥 영역을 클릭한 경우에도 메뉴가 닫히지 않도록 구현되어 있습니다. ```tsx import { Avatar } from "seed-design/ui/avatar"; import { IdentityPlaceholder } from "seed-design/ui/identity-placeholder"; import { IconPencilLine, IconPlusLine } from "@karrotmarket/react-monochrome-icon"; import { useState } from "react"; import { Switch } from "seed-design/ui/switch"; import { MenuAnchor, MenuContent, MenuGroup, MenuItem, MenuRoot } from "seed-design/ui/menu"; import { HStack } from "@seed-design/react"; export default function MenuAnchorExample() { const [open, setOpen] = useState(false); return ( { if (!nextOpen && details?.reason === "interactOutside") return; setOpen(nextOpen); }} > } /> } /> } /> ); } ``` ### Match Width `MenuRoot`의 `matchReferenceWidth` prop을 사용하면 메뉴의 너비가 reference 요소(Trigger 또는 Anchor)의 너비에 맞춰집니다. ```tsx import { ActionButton } from "seed-design/ui/action-button"; import { MenuContent, MenuGroup, MenuItem, MenuRoot, MenuTrigger } from "seed-design/ui/menu"; export default function MenuMatchReferenceWidth() { return ( 열기 ); } ``` ### `onOpenChange` Details `onOpenChange` 두 번째 인자로 `details`가 제공됩니다. #### `reason` **열릴 때** (`open: true`) - `"trigger"`: `MenuTrigger`로 열림 **닫힐 때** (`open: false`) - `"trigger"`: `MenuTrigger`로 닫힘 - `"escapeKeyDown"`: ESC 키 사용 - `"interactOutside"`: 외부 영역 클릭 - `"itemClick"`: 메뉴 항목 클릭 - `"cascadeDismiss"`: 상위 레이어 닫힘으로 인한 연쇄 닫힘 ```tsx import { IconPencilLine, IconPlusLine } from "@karrotmarket/react-monochrome-icon"; import { HStack, Text, VStack } from "@seed-design/react"; import { useState } from "react"; import { ActionButton } from "seed-design/ui/action-button"; import { MenuContent, MenuGroup, MenuItem, MenuRoot, MenuTrigger } from "seed-design/ui/menu"; export default function MenuOpenChangeReason() { const [open, setOpen] = useState(false); const [openReason, setOpenReason] = useState(null); const [closeReason, setCloseReason] = useState(null); return ( { setOpen(open); (open ? setOpenReason : setCloseReason)(details?.reason ?? null); }} > 열기 } /> } /> 마지막 열림 이유: {openReason ?? "-"} 마지막 닫힘 이유: {closeReason ?? "-"} ); } ```