DropdownMenu
먼저 보고, 그다음 계약을 읽습니다
버튼 클릭으로 여는 메뉴 — 액션·토글·라디오·단축키를 한 표면에 묶는다 (Radix DropdownMenu 기반).
Component intent의도와 경계 읽기
Popover 와 모양은 비슷하나 *메뉴 의미*(role=menu/menuitem, 항목 highlighted, 화살표 키 내비게이션)를 가진다. Radix DropdownMenu 위에 .axe-dropdown-menu__* 스타일만 입혔고, 위치 계산·키보드·type-ahead·focus 복원은 Radix 가 처리한다. DropdownMenu(Root)·DropdownMenuTrigger·DropdownMenuContent·DropdownMenuItem 를 기본 골격으로, Label·Separator·Shortcut·CheckboxItem·RadioGroup/RadioItem·Sub(SubTrigger/SubContent)·Arrow 를 조합해 쓴다.
예제
SSOT에 등록된 실제 API 기준 snippet입니다. standalone 배지만 독립 실행 단위이며, fragment는 주변 state·handler 문맥을 생략합니다.
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuShortcut, DropdownMenuSeparator,} from "@axe/ui";import { Button } from "@axe/ui";<DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="secondary">옵션</Button> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuLabel>액션</DropdownMenuLabel> <DropdownMenuItem onSelect={createNew}> 새 항목 <DropdownMenuShortcut>⌘N</DropdownMenuShortcut> </DropdownMenuItem> <DropdownMenuItem onSelect={rename}>이름 변경</DropdownMenuItem> <DropdownMenuSeparator /> <DropdownMenuItem variant="danger" onSelect={remove}>삭제</DropdownMenuItem> </DropdownMenuContent></DropdownMenu>import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent,} from "@axe/ui";import { Button } from "@axe/ui";<DropdownMenu> <DropdownMenuTrigger asChild> <Button>보기</Button> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuCheckboxItem checked={grid} onCheckedChange={setGrid}> 그리드 </DropdownMenuCheckboxItem> <DropdownMenuSeparator /> <DropdownMenuRadioGroup value={sort} onValueChange={setSort}> <DropdownMenuRadioItem value="name">이름순</DropdownMenuRadioItem> <DropdownMenuRadioItem value="date">날짜순</DropdownMenuRadioItem> </DropdownMenuRadioGroup> <DropdownMenuSeparator /> <DropdownMenuSub> <DropdownMenuSubTrigger>내보내기</DropdownMenuSubTrigger> <DropdownMenuSubContent> <DropdownMenuItem onSelect={exportCsv}>CSV</DropdownMenuItem> <DropdownMenuItem onSelect={exportPdf}>PDF</DropdownMenuItem> </DropdownMenuSubContent> </DropdownMenuSub> </DropdownMenuContent></DropdownMenu>Props
TSX 소스가 진실입니다. 주요 export 컴포넌트의 public API만 노출합니다.
| 이름 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
open | boolean | — | — | 열림 상태 (controlled). Radix Root prop. |
defaultOpen | boolean | — | — | uncontrolled 초기 열림 상태 (Root). |
onOpenChange | (open: boolean) => void | — | — | 열림/닫힘 콜백 (Root). |
modal | boolean | — | true | true 면 바깥 스크롤/포커스를 잠금 (Root). |
sideOffset | number | — | 6 | DropdownMenuContent 와 트리거 사이 간격(px). |
withPortal | boolean | — | true | DropdownMenuContent 를 portal 로 띄울지 — overflow:hidden 부모 탈출. |
variant | "default" | "danger" | — | "default" | DropdownMenuItem 톤. danger=파괴적 액션(삭제·로그아웃)의 텍스트/highlighted bg 를 danger 로. |
icon | React.ReactNode | — | — | DropdownMenuItem 좌측 아이콘 슬롯 (선택). |
...rest | 각 Radix DropdownMenu.* props | — | — | Trigger(asChild)·Content(side/align/collisionPadding)·Item(onSelect/disabled)·CheckboxItem/RadioItem(checked/value/onCheckedChange) 등 각 파트는 대응 Radix 컴포넌트 props 를 그대로 전파. |
.axe-* 클래스 계약
React 밖에서도 같은 표면을 그리는 공개 계약입니다. stable은 minor 버전 안에서 이름을 바꾸지 않습니다.
| 클래스 | 안정성 | 용도 |
|---|---|---|
.axe-dropdown-menu__content | stable | 포털로 뜨는 메뉴 패널 표면(elevated bg·border·shadow). |
.axe-dropdown-menu__sub-content | stable | 서브메뉴 패널 — 같은 표면 + 살짝 가벼운 그림자. |
.axe-dropdown-menu__item | stable | 메뉴 항목 row(좌 indicator/icon · 중 label · 우 shortcut). |
.axe-dropdown-menu__item--danger | stable | danger 변형 항목(텍스트+highlighted bg 가 danger 톤). |
.axe-dropdown-menu__label | stable | 그룹 제목(대문자 트래킹, tertiary 색). |
.axe-dropdown-menu__separator | stable | 그룹 구분선(1px border-subtle). |
.axe-dropdown-menu__shortcut | stable | 우측 정렬 단축키 힌트 슬롯(Kbd 래핑). |
.axe-dropdown-menu__arrow | stable | 트리거를 가리키는 화살표(Radix Arrow). |
.axe-dropdown-menu__item--checkbox | internal | checkbox 항목 — indicator 자리 확보 layout 변형(자동 적용). |
.axe-dropdown-menu__item--radio | internal | radio 항목 layout 변형(자동 적용). |
.axe-dropdown-menu__item--sub-trigger | internal | 서브메뉴 여는 항목 — 우측 chevron 포함 layout(자동 적용). |
.axe-dropdown-menu__item-indicator | internal | 체크/도트 표시 슬롯(Radix ItemIndicator). |
.axe-dropdown-menu__item-icon | internal | 항목 좌측 아이콘 슬롯 span. |
.axe-dropdown-menu__item-label | internal | 항목 가운데 라벨 span. |
.axe-dropdown-menu__sub-chevron | internal | sub-trigger 우측 chevron 아이콘. |
접근성
키보드, ARIA, 구현 노트를 함께 검토합니다.
- 트리거에서 Space/Enter/↓ 로 열기
- ↑/↓ 로 항목 이동, Home/End 로 처음/끝
- 글자 입력 시 type-ahead 로 해당 항목 점프
- → 로 서브메뉴 열기, ← 로 닫고 상위로
- Enter/Space 로 항목 실행, Esc 로 닫기(트리거로 포커스 복원)
Radix 가 트리거에 aria-haspopup=menu·aria-expanded 를, 콘텐츠에 role=menu, 각 항목에 role=menuitem(체크박스=menuitemcheckbox+aria-checked, 라디오=menuitemradio)을 부여. 현재 항목은 data-highlighted, 비활성은 data-disabled 로 표시.
modal 기본(바깥 클릭·스크롤 잠금). 열림 시 첫 항목으로 focus, 닫힘 시 트리거로 복원. prefers-reduced-motion 시 open/close 애니메이션 제거.