본문으로 건너뛰기
오버레이 / dropdown-menu

DropdownMenu

버튼 클릭으로 여는 메뉴 — 액션·토글·라디오·단축키를 한 표면에 묶는다 (Radix DropdownMenu 기반).
오버레이dropdown-menuStatic specimendropdownmenu드롭다운메뉴
01 · Specimen

먼저 보고, 그다음 계약을 읽습니다

버튼 클릭으로 여는 메뉴 — 액션·토글·라디오·단축키를 한 표면에 묶는다 (Radix DropdownMenu 기반).

Workbench 불러오는 중…
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 를 조합해 쓴다.

02 · Use

예제

SSOT에 등록된 실제 API 기준 snippet입니다. standalone 배지만 독립 실행 단위이며, fragment는 주변 state·handler 문맥을 생략합니다.

01기본 (라벨 · 단축키 · 구분선 · danger)tsxfragment
기본 (라벨 · 단축키 · 구분선 · danger)
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>
02체크박스 · 라디오 · 서브메뉴tsxfragment
체크박스 · 라디오 · 서브메뉴
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>
03 · React

Props

TSX 소스가 진실입니다. 주요 export 컴포넌트의 public API만 노출합니다.

이름타입필수기본값설명
openboolean열림 상태 (controlled). Radix Root prop.
defaultOpenbooleanuncontrolled 초기 열림 상태 (Root).
onOpenChange(open: boolean) => void열림/닫힘 콜백 (Root).
modalbooleantruetrue 면 바깥 스크롤/포커스를 잠금 (Root).
sideOffsetnumber6DropdownMenuContent 와 트리거 사이 간격(px).
withPortalbooleantrueDropdownMenuContent 를 portal 로 띄울지 — overflow:hidden 부모 탈출.
variant"default" | "danger""default"DropdownMenuItem 톤. danger=파괴적 액션(삭제·로그아웃)의 텍스트/highlighted bg 를 danger 로.
iconReact.ReactNodeDropdownMenuItem 좌측 아이콘 슬롯 (선택).
...rest각 Radix DropdownMenu.* propsTrigger(asChild)·Content(side/align/collisionPadding)·Item(onSelect/disabled)·CheckboxItem/RadioItem(checked/value/onCheckedChange) 등 각 파트는 대응 Radix 컴포넌트 props 를 그대로 전파.
04 · Any stack

.axe-* 클래스 계약

React 밖에서도 같은 표면을 그리는 공개 계약입니다. stable은 minor 버전 안에서 이름을 바꾸지 않습니다.

클래스안정성용도
.axe-dropdown-menu__contentstable포털로 뜨는 메뉴 패널 표면(elevated bg·border·shadow).
.axe-dropdown-menu__sub-contentstable서브메뉴 패널 — 같은 표면 + 살짝 가벼운 그림자.
.axe-dropdown-menu__itemstable메뉴 항목 row(좌 indicator/icon · 중 label · 우 shortcut).
.axe-dropdown-menu__item--dangerstabledanger 변형 항목(텍스트+highlighted bg 가 danger 톤).
.axe-dropdown-menu__labelstable그룹 제목(대문자 트래킹, tertiary 색).
.axe-dropdown-menu__separatorstable그룹 구분선(1px border-subtle).
.axe-dropdown-menu__shortcutstable우측 정렬 단축키 힌트 슬롯(Kbd 래핑).
.axe-dropdown-menu__arrowstable트리거를 가리키는 화살표(Radix Arrow).
.axe-dropdown-menu__item--checkboxinternalcheckbox 항목 — indicator 자리 확보 layout 변형(자동 적용).
.axe-dropdown-menu__item--radiointernalradio 항목 layout 변형(자동 적용).
.axe-dropdown-menu__item--sub-triggerinternal서브메뉴 여는 항목 — 우측 chevron 포함 layout(자동 적용).
.axe-dropdown-menu__item-indicatorinternal체크/도트 표시 슬롯(Radix ItemIndicator).
.axe-dropdown-menu__item-iconinternal항목 좌측 아이콘 슬롯 span.
.axe-dropdown-menu__item-labelinternal항목 가운데 라벨 span.
.axe-dropdown-menu__sub-chevroninternalsub-trigger 우측 chevron 아이콘.
비-React 소비 노트
위치 계산·열림/닫힘·항목 하이라이트가 Radix 런타임(data-state, data-highlighted)에 의존해 CSS-only 로는 동작하는 메뉴를 재현할 수 없다. .axe-dropdown-menu__* 토큰은 정적 표면 렌더에 노출되나 실제 소비는 React 컴포넌트를 통해서 한다. ContextMenu 가 동일한 이 표면 클래스를 공유한다.
05 · Inclusive

접근성

키보드, ARIA, 구현 노트를 함께 검토합니다.

Keyboard
  • 트리거에서 Space/Enter/↓ 로 열기
  • ↑/↓ 로 항목 이동, Home/End 로 처음/끝
  • 글자 입력 시 type-ahead 로 해당 항목 점프
  • → 로 서브메뉴 열기, ← 로 닫고 상위로
  • Enter/Space 로 항목 실행, Esc 로 닫기(트리거로 포커스 복원)
ARIA

Radix 가 트리거에 aria-haspopup=menu·aria-expanded 를, 콘텐츠에 role=menu, 각 항목에 role=menuitem(체크박스=menuitemcheckbox+aria-checked, 라디오=menuitemradio)을 부여. 현재 항목은 data-highlighted, 비활성은 data-disabled 로 표시.

Notes

modal 기본(바깥 클릭·스크롤 잠금). 열림 시 첫 항목으로 focus, 닫힘 시 트리거로 복원. prefers-reduced-motion 시 open/close 애니메이션 제거.

06 · Judgment

권장 · 지양

권장
  • 트리거는 asChild 로 Button 등 실제 인터랙티브 요소에 씌운다.
  • 파괴적 항목은 variant="danger" + 구분선으로 안전 항목과 분리.
  • 단축키가 있으면 DropdownMenuShortcut 으로 우측에 힌트.
지양
  • 메뉴 안에 폼 입력·긴 인터랙티브 컨텐츠를 넣지 말 것 — 그 자리는 Popover/Dialog.
  • 아이콘만 있는 트리거에 접근 가능한 이름(aria-label)을 빠뜨리지 말 것.
검색창을 열면 컴포넌트 인덱스를 불러옵니다.