Menu#
Menu 는 테두리가 있는 패널 안에 풍부한 메뉴 항목 목록을 표시하는
정적(인라인) 메뉴 컴포넌트입니다. 항목은 CoreMenuItem 의 이름 있는
팩토리 생성자로 만듭니다 — 헤딩 라벨, 액션, 체크박스, 라디오, 구분선,
간격, 그리고 인라인 중첩 서브메뉴까지 지원합니다.
Live Preview#
Web
Flutter
class MenuDefaultExample extends StatelessComponent {
const MenuDefaultExample({super.key});
@override
Component build(BuildContext context) {
return Menu(
ariaLabel: 'Main menu',
items: [
const CoreMenuItem.label('Navigation'),
CoreMenuItem.action('Home', onPressed: () {}, active: true),
CoreMenuItem.action('Profile', onPressed: () {}),
const CoreMenuItem.divider(),
CoreMenuItem.checkbox('Show grid', onChanged: (_) {}, checked: true),
CoreMenuItem.action('Settings', disabled: true),
],
);
}
}
class MenuDefaultExample extends StatelessWidget {
const MenuDefaultExample({super.key});
@override
Widget build(BuildContext context) {
return Menu(
ariaLabel: 'Main menu',
items: [
const CoreMenuItem.label('Navigation'),
CoreMenuItem.action('Home', onPressed: () {}, active: true),
CoreMenuItem.action('Profile', onPressed: () {}),
const CoreMenuItem.divider(),
CoreMenuItem.checkbox('Show grid', onChanged: (_) {}, checked: true),
CoreMenuItem.action('Settings', disabled: true),
],
);
}
}
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- 액션이나 네비게이션 항목 목록을 패널로 직접 표시할 때
- leading/trailing 아이콘, 체크박스, 라디오를 포함한 메뉴가 필요할 때
- 인라인으로 펼쳐지는 계층적 서브메뉴 구조가 필요할 때
대신 다른 컴포넌트를 사용하세요:
DropdownMenu: 트리거 클릭으로 떠오르는 오버레이 메뉴일 때ContextMenu: 우클릭/롱프레스로 여는 컨텍스트 메뉴일 때Menubar: 가로 애플리케이션 메뉴바일 때Select: 폼에서 값을 선택하는 드롭다운일 때
기본 사용법 (Basic Usage)#
Menu(
ariaLabel: 'Main menu',
items: [
const CoreMenuItem.label('Navigation'),
CoreMenuItem.action('Home', onPressed: () {}, active: true),
CoreMenuItem.action('Profile', onPressed: () {}),
const CoreMenuItem.divider(),
CoreMenuItem.checkbox('Show grid', onChanged: (_) {}, checked: true),
CoreMenuItem.action('Settings', disabled: true),
],
)
Menu(
ariaLabel: 'Main menu',
items: [
const CoreMenuItem.label('Navigation'),
CoreMenuItem.action('Home', onPressed: () {}, active: true),
CoreMenuItem.action('Profile', onPressed: () {}),
const CoreMenuItem.divider(),
CoreMenuItem.checkbox('Show grid', onChanged: (_) {}, checked: true),
CoreMenuItem.action('Settings', disabled: true),
],
)
Props / Parameters#
Menu#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
items |
List<CoreMenuItem<W>> |
필수 | 패널에 렌더링할 메뉴 항목 |
vertical |
bool |
true |
false 면 항목을 가로로 배치 |
ariaLabel |
String? |
null |
메뉴 컨테이너의 접근성 이름 |
menuStyle |
CoreMenuStyle? |
null |
인스턴스별 chrome 스타일 |
CoreMenuItem 팩토리#
| 팩토리 | 설명 |
|---|---|
CoreMenuItem.label(text, {leading, trailing}) | 비대화 섹션 헤딩 |
CoreMenuItem.action(text, {leading, trailing, onPressed, href, submenu, active, disabled})
|
대화형 액션 항목 (submenu 지정 시 인라인 서브메뉴 트리거) |
CoreMenuItem.checkbox(text, {trailing, onChanged, checked, disabled}) |
체크박스 토글 항목 |
CoreMenuItem.radio(text, {trailing, onChanged, selected, disabled}) |
라디오 단일 선택 항목 |
CoreMenuItem.divider() | 시각적 구분선 |
CoreMenuItem.gap(size) | 고정 크기 간격 |
스타일 시스템 (Style System)#
Menu 의 모든 chrome / dimensional 오버라이드는 단일 CoreMenuStyle
슬롯으로 흐릅니다.
시맨틱 vs 스타일#
- 시맨틱 / behaviour: 위젯 파라미터로 직접 (
vertical,ariaLabel) -
chrome / dimensional:
CoreMenuStyle한 곳으로 (background / border / radius / padding / itemPadding / itemSpacing / itemContentGapStyle / activeColor / hoverColor / dividerColor / leadingColumnWidth / submenuIndent)
Resolve chain#
CoreMenuStyle.defaultX (디자인 시스템 기본값)
→ CoreMenuTheme.style // 프로젝트 공통
→ widget.menuStyle // 인스턴스별
사용 예#
Menu(
items: items,
menuStyle: const CoreMenuStyle(
borderRadius: CoreBorderRadius.all(CoreRadius.radius12),
activeColor: CoreColor.token(CoreColors.secondary),
),
)
변형 (Variants)#
서브메뉴 (인라인 중첩)#
Menu(
items: [
CoreMenuItem.action('File', onPressed: () {}),
CoreMenuItem.action(
'Export',
submenu: [
CoreMenuItem.action('PDF', onPressed: () {}),
CoreMenuItem.action('CSV', onPressed: () {}),
],
),
],
)
서브메뉴는 부모 항목 아래에 한 단계 들여쓰기되어 인라인으로 펼쳐집니다.
가로 메뉴#
Menu(
vertical: false,
items: [
CoreMenuItem.action('Home', onPressed: () {}),
CoreMenuItem.action('Docs', onPressed: () {}),
],
)
체크 / 라디오 항목#
Menu(
items: [
CoreMenuItem.checkbox('Auto save', onChanged: (_) {}, checked: true),
CoreMenuItem.radio('Compact', onChanged: (_) {}, selected: true),
CoreMenuItem.radio('Comfortable', onChanged: (_) {}),
],
)
동작 스펙 (Behavior)#
항목 활성화#
- action: 클릭/탭으로
onPressed호출.disabled면 무시 + 0.5 불투명도 - checkbox: 활성화 시
onChanged(!checked)호출, 체크 시 leading 체크 아이콘 표시 - radio: 활성화 시
onChanged(true)호출, 선택 시 leading dot 아이콘 표시
Hover#
- 대화형 항목에 포인터를 올리면
hoverColor배경이 표시됩니다.
서브메뉴#
-
CoreMenuItem.action에submenu를 지정하면 trailing 위치에 chevron 아이콘이 자동 추가되고, 항목 아래에 중첩Menu가 인라인으로 렌더됩니다.
접근성 (Accessibility)#
스크린 리더#
- Flutter:
ariaLabel이Semantics컨테이너 라벨로 노출됩니다. -
Web:
role="menu"(세로) /role="menubar"(가로), 항목별role="menuitem"/menuitemcheckbox/menuitemradio,aria-orientation,aria-disabled,aria-current,aria-checked로 상태를 전달합니다.
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 패널 | Container + Column/Row |
<div> flex 패널 |
| 항목 | CoreMenuItem 팩토리 (양쪽 동일 API) |
CoreMenuItem 팩토리 (양쪽 동일 API) |
| 구분선 | Separator | <hr> (border 기반) |
| 서브메뉴 | 인라인 중첩 Menu | 인라인 중첩 Menu |
| 아이콘 | Icon | Icon |
| ARIA | Flutter Semantics |
role / aria-* 속성 |
관련 컴포넌트 (Related Components)#
- DropdownMenu: 트리거로 떠오르는 오버레이 메뉴
- ContextMenu: 우클릭/롱프레스 컨텍스트 메뉴
- Menubar: 가로 애플리케이션 메뉴바
- Popover: 임의의 콘텐츠를 표시하는 팝업