DropdownMenu#
버튼 등 트리거 요소를 클릭하면 액션 목록을 떠 있는 패널로 표시하는 드롭다운 메뉴 컴포넌트입니다. 액션 행과 구분선, 키보드 단축키 힌트를 지원합니다.
DropdownMenu는 레거시 Flutter DropdownMenu와 Web DropdownMenu를 통일한
컴포넌트입니다. Flutter와 Web이 동일한 파라미터 이름·동작·시각을 갖습니다 —
패널은 양쪽 모두 루트 오버레이로 portal되어 ancestor overflow에 잘리지
않습니다.
Live Preview#
class DropdownMenuDefaultExample extends StatelessComponent {
const DropdownMenuDefaultExample({super.key});
@override
Component build(BuildContext context) {
return DropdownMenu(
trigger: Button(
variant: CoreButtonVariant.outline,
onPressed: () {},
child: Text('Open Menu'),
),
items: [
CoreMenuItem.action('Profile', onPressed: () {}),
CoreMenuItem.action('Settings', onPressed: () {}),
const CoreMenuItem.divider(),
CoreMenuItem.action('Sign out', onPressed: () {}),
],
);
}
}
class DropdownMenuDefaultExample extends StatelessWidget {
const DropdownMenuDefaultExample({super.key});
@override
Widget build(BuildContext context) {
return DropdownMenu(
trigger: Button(
variant: CoreButtonVariant.outline,
onPressed: () {},
child: const Text('Open Menu'),
),
items: [
CoreMenuItem.action('Profile', onPressed: () {}),
CoreMenuItem.action('Settings', onPressed: () {}),
const CoreMenuItem.divider(),
CoreMenuItem.action('Sign out', onPressed: () {}),
],
);
}
}
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- "더보기" 버튼에 편집 / 공유 / 삭제 등 액션 목록을 표시할 때
- 특정 버튼 클릭에 반응하는 컨텍스트 액션 메뉴가 필요할 때
대신 다른 컴포넌트를 사용하세요:
Select: 값을 선택하는 폼 입력에ContextMenu: 우클릭으로 표시되는 상황별 메뉴에Menubar: 데스크탑 앱 스타일의 상단 가로 메뉴 바에
기본 사용법 (Basic Usage)#
DropdownMenu(
trigger: Button(
variant: CoreButtonVariant.outline,
onPressed: () {},
child: const Text('Open Menu'),
),
items: [
CoreMenuItem.action('Profile', onPressed: () {}),
CoreMenuItem.action('Settings', onPressed: () {}),
const CoreMenuItem.divider(),
CoreMenuItem.action('Sign out', onPressed: () {}),
],
)
DropdownMenu(
trigger: Button(
variant: CoreButtonVariant.outline,
onPressed: () {},
child: Text('Open Menu'),
),
items: [
CoreMenuItem.action('Profile', onPressed: () {}),
CoreMenuItem.action('Settings', onPressed: () {}),
const CoreMenuItem.divider(),
CoreMenuItem.action('Sign out', onPressed: () {}),
],
)
Props / Parameters#
DropdownMenu#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
trigger | W | 필수 | 메뉴를 여는 트리거 요소 |
items |
List<CoreMenuItem<W>> |
필수 |
드롭다운 패널의 행 —
Menu
/
Menubar
/
ContextMenu
와 공유하는 통합 [CoreMenuItem] 모델
|
popupStyle |
CorePopupStyle? |
null |
인스턴스별 패널 chrome 스타일 |
controller |
PopoverController? |
null |
외부에서 열기/닫기를 명령형으로 제어 (Popover 와 동일한 통합 컨트롤러) |
CoreMenuItem (드롭다운에서 쓰는 종류)#
드롭다운은 통합 CoreMenuItem 모델을 받는다. 주로 쓰는 두 종류:
| 생성자 | 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|---|
.action |
label (positional) |
String |
필수 | 액션 행 텍스트 |
.action |
shortcut |
String? |
null |
라벨 뒤에 표시되는 단축키 힌트 |
.action |
disabled |
bool |
false |
true 시 muted 처리 + onPressed 미호출 |
.action |
onPressed |
void Function()? |
null |
활성 액션 선택 시 호출 |
.divider | — | — | — | 그룹 사이 구분선 |
스타일 시스템 (Style System)#
DropdownMenu의 드롭다운 패널은 떠 있는 popup 표면이므로 CorePopupStyle
chrome 슬롯을 공유합니다 (Epic #1415 option D). 패널의 보더 / 반경 / 배경 /
그림자 / 패딩 / 최소 너비가 모두 popupStyle 한 곳으로 흐릅니다.
Resolve chain#
CorePopupStyle.defaultX // 디자인 시스템 기본값
→ CorePopupTheme.style // 프로젝트 공통
→ widget.popupStyle // 인스턴스별
엔트리 행 chrome (패딩 / hover 배경 / 구분선 색)은 CoreDropdownMenuStyle의
defaultEntryPadding / defaultEntryBorderRadius
/ defaultEntryHoverColor /
defaultDividerColor / defaultEntryDuration 디자인 시스템 기본값으로
고정되어 앱 전체에서 일관성을 유지합니다.
DropdownMenu(
popupStyle: const CorePopupStyle(
borderRadius: CoreBorderRadius.all(CoreRadius.radius16),
),
trigger: const Text('Menu'),
items: const [CoreMenuItem.action('Item')],
)
변형 (Variants)#
단축키 힌트 / 비활성 엔트리#
DropdownMenu(
trigger: const Text('Edit'),
items: const [
CoreMenuItem.action('Undo', shortcut: 'Ctrl+Z'),
CoreMenuItem.action('Redo', disabled: true),
],
)
동작 스펙 (Behavior)#
인터랙션#
- 트리거 클릭: 메뉴 열기 / 닫기 토글
- 항목 선택: 활성 항목 클릭 시
onPressed호출 후 닫힘 - 외부 클릭: 메뉴 외부 클릭 시 닫힘
- Escape: 열린 메뉴 닫힘
애니메이션#
- 엔트리 hover 배경: 150ms 색상 전환 (
CoreDuration.ms150)
사용 가이드라인 (Usage Guidelines)#
✅ Do#
관련 액션을 구분선으로 그룹화
DropdownMenu(
trigger: const Text('More'),
items: const [
CoreMenuItem.action('Edit'),
CoreMenuItem.action('Duplicate'),
CoreMenuItem.divider(),
CoreMenuItem.action('Delete'),
],
)
구분선으로 관련 액션을 묶으면 메뉴 탐색이 더 직관적이다.
❌ Don't#
폼 값 선택에 DropdownMenu 사용
// ❌ 값 선택 폼
DropdownMenu(
trigger: const Text('Country'),
items: const [CoreMenuItem.action('Korea')],
)
폼에서 값을 선택할 때는 Select가 레이블·유효성 검사·접근성을 더 잘 지원한다.
접근성 (Accessibility)#
시맨틱 역할#
- 트리거:
role="button"+aria-haspopup+aria-expanded(Web) - 드롭다운 패널:
role="menu" - 엔트리:
role="menuitem"(비활성 시aria-disabled) - 구분선:
role="separator"
키보드 인터랙션#
| 키 | 동작 |
|---|---|
Escape | 열린 메뉴 닫기 |
크로스 플랫폼 차이점 (Platform Differences)#
DropdownMenu는 Flutter와 Web이 동일한 trigger / items /
popupStyle API와 동작을 갖습니다. 드롭다운 패널은 Flutter에서는
OverlayPortal, Web에서는 루트 OverlayHost의 menu 레이어로 portal되어
양쪽 모두 ancestor overflow에 잘리지 않습니다.
관련 컴포넌트 (Related Components)#
- Menu: 사이드바 형태의 일반 메뉴
- ContextMenu: 우클릭 상황별 메뉴
- Popup: 플로팅 패널 컨테이너