Tiro
Tiro Design
Components

DropdownMenu

컨텍스트 액션 메뉴. 트리거 버튼을 누르면 옵션 리스트 표시.

Aliases (deprecated): LanguageDropdown, NoteDropdownBase, NoteOptionsDropdown, NoteShareDropdown — 모두 DropdownMenu + item schema로 이관.

Mobile

모바일에서 DropdownMenu는 Action Sheet 형태의 BottomSheet로 변환된다. 트리거 근처에 떠 있는 desktop popover 대신, 화면 하단에서 슬라이드 업 후 액션 항목을 세로 리스트로 표시한다.

  • 컨테이너 anatomy(detents·grabber·swipe-to-dismiss·safe area)는 Dialog → Mobile Presentation 참조
  • 액션 항목: 세로 스택, 각 행 높이 ≥44pt (터치 타겟), 좌측 prefix 아이콘 + 라벨, 우측 trailing affordance(예: checkmark, chevron) 가능
  • Destructive 액션은 rose-600 텍스트로 표시, 시각적 그룹 분리(separator 위)
  • 드래그 다운/외부 탭으로 dismiss. "취소" 버튼을 footer로 두는 iOS Action Sheet 관례를 따라도 좋음 (선택적)
  • 트리거 종류: header의 "more" 버튼(MoreHorizontal), 리스트 행의 long-press, 컨텍스트 액션 버튼

Preview

Anatomy

DropdownMenu는 trigger 클릭으로 열리는 액션 리스트. Popover와 다름 (Popover는 자유 콘텐츠, DropdownMenu는 menu items 전용).

DropdownMenuRoot
├─ DropdownMenuTrigger        (외부 element — Button)
└─ DropdownMenuContent
   ├─ DropdownMenuLabel       (optional, 그룹 헤더 — Text · caption1Medium uppercase)
   ├─ DropdownMenuItem        (×N)
   │  ├─ ItemLeading          (optional, Icon · Avatar)
   │  ├─ ItemLabel            (Text · label3Medium)
   │  └─ ItemTrailing         (optional, Shortcut · Chevron · Check)
   ├─ DropdownMenuSeparator   (optional, 그룹 구분)
   ├─ DropdownMenuSub         (optional, 서브메뉴)
   │  ├─ DropdownMenuSubTrigger (Item with Chevron)
   │  └─ DropdownMenuSubContent (재귀 구조)
   └─ DropdownMenuItem destructive (optional, 마지막에 배치)

슬롯 규칙

SlotRequiredPrimitive비고
DropdownMenuTriggeralways(외부)Button · IconButton — icon-only일 때 aria-label 필수
DropdownMenuContentalwaysbg-white, border-tds-stone-100, rounded-lg, shadow-md, min-w-[160px]
DropdownMenuLabeloptionalTextcaption1Medium uppercase, color muted-foreground
DropdownMenuItem≥1h-7 px-2 (28px), rounded-md, hover bg-stone-50
ItemLeadingoptionalIcon (16px) · Avatar (sm 32)menu item 좌측
ItemLabelalwaysTextlabel3Medium 12/18 Medium
ItemTrailingoptionalText (shortcut) · Icon (Chevron / Check)submenu = Chevron, 토글 = Check
DropdownMenuSeparatoroptional1px solid stone-100, my-1
Destructive itemoptionaltext + icon text-rose-500, hover bg-rose-50. 마지막 위치

Layout invariants

  • Item 높이 h-7 일관 (Select item과 동일한 28px)
  • Destructive item은 항상 list 마지막, separator로 분리 권장
  • ItemLeading 있으면 다른 item에도 일관 적용 (icon column align)
  • Submenu는 right 방향 자동 (Radix Popper)
  • Esc/외부 클릭/item 선택으로 close

Variants

  • context — 더보기/옵션 메뉴 (기본)
  • selection — 선택 반영 (트리거 라벨에 선택값 표시 필요 시 Select 고려)
  • checkbox — 다중 선택 (체크 표시)
  • radio — 단일 선택
  • submenu — 하위 메뉴 중첩

Token Mapping

TokenValue (web)Value (mobile — Action Sheet)Description
presentationpopover (트리거 근처 floating)BottomSheet (화면 하단 슬라이드 업)모바일은 Action Sheet 패턴
bgbg-whitebg-white
borderborder-tds-stone-100없음 (시트가 컨테이너)stone-100 = #E7E5E4
radiusrounded-lg (8px)top corners only r4 (16px)
item heighth-7 (28px)≥44pt (iOS HIG)액션 행 높이
item radiusrounded-md없음 (full-width row)
item hover/pressedfocus:bg-tds-stone-50pressed:bg-stone-50
item texttext-tds-stone-600text-stone-700 (모바일 가독성)
item typographytypography-label3Medium (12/18)label1Medium (14/20) (모바일 가독성)Select item과 동일
item icon좌측 prefix 16px동일 (좌측 16-20px)
danger item texttext-tds-rose-500text-rose-600파괴 액션
danger item hover/pressedfocus:bg-tds-rose-50pressed:bg-rose-50
separatorbg-tds-stone-100bg-stone-100, full-width섹션 구분
elevationLevel 2 (shadow-md)native sheet elevation
z-indexz-popup (100000)시트 컨테이너가 처리
min-widthmin-w-[160px]100vw (full-width)
dismissoverlay 클릭 / Esc / 항목 선택드래그 다운 / 외부 탭 / 항목 선택iOS Action Sheet에 "취소" footer 추가 가능

Props

type DropdownMenuProps = {
  items: Array<{
    key: string;
    label: string;
    icon?: ReactNode;
    shortcut?: string; // "⌘K" 등
    disabled?: boolean;
    danger?: boolean;
    submenu?: DropdownMenuProps["items"];
  }>;
  onSelect: (key: string) => void;
  trigger: ReactNode;
};

Usage

<DropdownMenu
  trigger={<Button type="ghost" layout="icon-only" aria-label="더보기"><MoreIcon /></Button>}
  items={[
    { key: "rename", label: "이름 바꾸기", icon: <EditIcon /> },
    { key: "share", label: "공유", icon: <ShareIcon /> },
    {
      key: "export",
      label: "내보내기",
      submenu: [
        { key: "pdf", label: "PDF" },
        { key: "docx", label: "Word (.docx)" },
      ],
    },
    { key: "delete", label: "삭제", icon: <TrashIcon />, danger: true },
  ]}
  onSelect={handleAction}
/>

A11y

  • role="menu" + 내부 role="menuitem" 자동
  • Arrow key 탐색, Enter/Space 선택, Esc 닫기
  • Roving focus

Do / Don't

  • Do: 공간 절약이 필요한 액션 집합에 사용
  • Do: 파괴적 item은 하단 섹션, separator로 분리
  • Don't: 선택값이 트리거 라벨이 되어야 하면 Select 사용
  • Don't: item 8개 이상이면 Command 또는 검색 가능한 Combobox 고려

On this page