Menubar
Menubar (메뉴바)
Menubar는 데스크톱 앱에서 흔히 볼 수 있는 것처럼, 자주 쓰는 명령들의 일관된 집합을 제공하는 시각적으로 상시 표시되는 메뉴를 만들기 위한 React 컴포넌트예요. 접근성이 뛰어난 애플리케이션 메뉴를 간편하게 구성할 수 있어요.
출처: 문서
본문
메뉴바는 데스크톱 애플리케이션에서 흔히 볼 수 있는 것과 유사한, 자주 쓰는 명령들의 일관된 집합을 제공하는 상시 표시 메뉴예요.
Material UI는 메뉴바 컴포넌트를 기본으로 제공하지는 않지만, 이 페이지에서는 Base UI Menubar로 구성하고 Material Design(MD2) 명세에 맞춰 스타일링한 컴포넌트들을 소개해요. 그래서 Material UI와 함께 사용할 수 있어요.
따라서 진행하기 전에 Base UI를 설치해야 해요. 아래 예시들은 그대로 복사해서 앱에 붙여넣으면 돼요. Base UI는 tree-shakeable이라 최종 번들에는 프로젝트에서 실제로 사용하는 컴포넌트만 포함돼요.
npm install @base-ui/react
pnpm add @base-ui/react
yarn add @base-ui/react
사용법 (Usage)
- 아래 데모 중 시각적 디자인에 맞는 것을 하나 고르세요.
- 툴바에서 Expand code를 클릭하세요.
./Menubar로 시작하는 파일을 선택하세요.- 코드를 복사해서 프로젝트에 붙여넣으세요.
기본 메뉴바 (Basic menubar)
기본 메뉴바 컴포넌트는 메뉴 항목들을 담은 드롭다운을 가진 메뉴 트리거들의 한 줄을 표시해요.
import * as React from 'react';
import {
Menubar,
MenuRoot,
MenuTrigger,
MenuPortal,
MenuPositioner,
MenuPopup,
MenuItem,
MenuSeparator,
MenuSubmenuRoot,
MenuSubmenuTrigger,
} from './components/Menubar';
export default function BasicMenubar() {
return (
<Menubar>
<MenuRoot>
<MenuTrigger>File</MenuTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4} alignOffset={-2}>
<MenuPopup>
<MenuItem>New</MenuItem>
<MenuItem>Open…</MenuItem>
<MenuItem>Save</MenuItem>
<MenuItem>Save as…</MenuItem>
<MenuSeparator />
<MenuSubmenuRoot>
<MenuSubmenuTrigger>Share</MenuSubmenuTrigger>
<MenuPortal>
<MenuPositioner alignOffset={-4}>
<MenuPopup>
<MenuItem>Email link</MenuItem>
<MenuItem>Copy link</MenuItem>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuSubmenuRoot>
<MenuSeparator />
<MenuItem>Close</MenuItem>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuRoot>
<MenuRoot>
<MenuTrigger>Help</MenuTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4}>
<MenuPopup>
<MenuItem>Documentation</MenuItem>
<MenuItem>Release notes</MenuItem>
<MenuSeparator />
<MenuItem>About</MenuItem>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuRoot>
</Menubar>
);
}
단축키 힌트 (Shortcut hints)
hint prop을 사용해서 메뉴 항목 옆에 키보드 단축키를 표시할 수 있어요.
import * as React from 'react';
import {
Menubar,
MenuRoot,
MenuTrigger,
MenuPortal,
MenuPositioner,
MenuPopup,
MenuItem,
MenuSeparator,
} from './components/Menubar';
export default function ShortcutHintsMenubar() {
return (
<Menubar>
<MenuRoot>
<MenuTrigger>File</MenuTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4} alignOffset={-2}>
<MenuPopup>
<MenuItem hint="⌘N">New</MenuItem>
<MenuItem hint="⌘O">Open…</MenuItem>
<MenuItem hint="⌘S">Save</MenuItem>
<MenuItem hint="⇧⌘S">Save As…</MenuItem>
<MenuSeparator />
<MenuItem hint="⌘P">Print…</MenuItem>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuRoot>
<MenuRoot>
<MenuTrigger>Edit</MenuTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4} alignOffset={-2}>
<MenuPopup>
<MenuItem hint="⌘Z">Undo</MenuItem>
<MenuItem hint="⇧⌘Z">Redo</MenuItem>
<MenuSeparator />
<MenuItem hint="⌘X">Cut</MenuItem>
<MenuItem hint="⌘C">Copy</MenuItem>
<MenuItem hint="⌘V">Paste</MenuItem>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuRoot>
</Menubar>
);
}
체크박스 항목 (Checkbox items)
각각 독립적으로 켜고 끌 수 있는 토글 옵션을 만들 때 사용해요.
import * as React from 'react';
import {
Menubar,
MenuRoot,
MenuTrigger,
MenuPortal,
MenuPositioner,
MenuPopup,
MenuItem,
MenuCheckboxItem,
MenuSeparator,
} from './components/Menubar';
export default function CheckboxItemsMenubar() {
const [showSidebar, setShowSidebar] = React.useState(true);
const [showToolbar, setShowToolbar] = React.useState(true);
const [showStatusBar, setShowStatusBar] = React.useState(false);
const [googleTasks, setGoogleTasks] = React.useState(true);
const [mail, setMail] = React.useState(false);
const [messages, setMessages] = React.useState(false);
return (
<Menubar>
<MenuRoot>
<MenuTrigger>View</MenuTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4} alignOffset={-2}>
<MenuPopup>
<MenuCheckboxItem
checked={showSidebar}
onCheckedChange={setShowSidebar}
>
Show Sidebar
</MenuCheckboxItem>
<MenuCheckboxItem
checked={showToolbar}
onCheckedChange={setShowToolbar}
>
Show Toolbar
</MenuCheckboxItem>
<MenuCheckboxItem
checked={showStatusBar}
onCheckedChange={setShowStatusBar}
>
Show Status Bar
</MenuCheckboxItem>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuRoot>
<MenuRoot>
<MenuTrigger>Window</MenuTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4} alignOffset={-2}>
<MenuPopup>
<MenuItem hint="⌘M">Minimize</MenuItem>
<MenuItem>Zoom</MenuItem>
<MenuItem hint="⌃⌥F">Fill</MenuItem>
<MenuItem hint="⌃⌥C">Center</MenuItem>
<MenuSeparator />
<MenuItem>Bring All to Front</MenuItem>
<MenuSeparator />
<MenuCheckboxItem
checked={googleTasks}
onCheckedChange={setGoogleTasks}
>
Google Tasks - Tasks
</MenuCheckboxItem>
<MenuCheckboxItem checked={mail} onCheckedChange={setMail}>
Mail
</MenuCheckboxItem>
<MenuCheckboxItem checked={messages} onCheckedChange={setMessages}>
Messages
</MenuCheckboxItem>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuRoot>
</Menubar>
);
}
라디오 그룹 항목 (Radio group items)
한 번에 하나만 선택할 수 있는 상호 배타적인 옵션을 만들 때 사용해요.
import * as React from 'react';
import {
Menubar,
MenuRoot,
MenuTrigger,
MenuPortal,
MenuPositioner,
MenuPopup,
MenuRadioGroup,
MenuRadioItem,
MenuSeparator,
MenuSubmenuRoot,
MenuSubmenuTrigger,
} from './components/Menubar';
export default function RadioGroupItemsMenubar() {
const [theme, setTheme] = React.useState('system');
const [density, setDensity] = React.useState('compact');
return (
<Menubar>
<MenuRoot>
<MenuTrigger>Appearance</MenuTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4} alignOffset={-2}>
<MenuPopup>
<MenuSubmenuRoot>
<MenuSubmenuTrigger>Theme</MenuSubmenuTrigger>
<MenuPortal>
<MenuPositioner alignOffset={-4}>
<MenuPopup>
<MenuRadioGroup value={theme} onValueChange={setTheme}>
<MenuRadioItem value="light">Light</MenuRadioItem>
<MenuRadioItem value="dark">Dark</MenuRadioItem>
<MenuRadioItem value="system">System</MenuRadioItem>
</MenuRadioGroup>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuSubmenuRoot>
<MenuSeparator />
<MenuRadioGroup value={density} onValueChange={setDensity}>
<MenuRadioItem value="compact">Compact</MenuRadioItem>
<MenuRadioItem value="comfortable">Comfortable</MenuRadioItem>
</MenuRadioGroup>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuRoot>
</Menubar>
);
}
아이콘 메뉴 항목 (Icon menu items)
icon prop을 써서 메뉴 항목에 아이콘을 추가하면 시각적으로 더 빨리 인식할 수 있어요.
import * as React from 'react';
import AddIcon from '@mui/icons-material/Add';
import FolderOpenIcon from '@mui/icons-material/FolderOpen';
import SaveIcon from '@mui/icons-material/Save';
import PrintIcon from '@mui/icons-material/Print';
import UndoIcon from '@mui/icons-material/Undo';
import RedoIcon from '@mui/icons-material/Redo';
import {
Menubar,
MenuRoot,
MenuTrigger,
MenuPortal,
MenuPositioner,
MenuPopup,
MenuItem,
MenuSeparator,
} from './components/Menubar';
export default function IconItemsMenubar() {
return (
<Menubar>
<MenuRoot>
<MenuTrigger>File</MenuTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4} alignOffset={-2}>
<MenuPopup>
<MenuItem icon={<AddIcon fontSize="small" />}>New</MenuItem>
<MenuItem icon={<FolderOpenIcon fontSize="small" />}>Open…</MenuItem>
<MenuItem icon={<SaveIcon fontSize="small" />}>Save</MenuItem>
<MenuSeparator />
<MenuItem icon={<PrintIcon fontSize="small" />}>Print…</MenuItem>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuRoot>
<MenuRoot>
<MenuTrigger>Edit</MenuTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4} alignOffset={-2}>
<MenuPopup>
<MenuItem icon={<UndoIcon fontSize="small" />}>Undo</MenuItem>
<MenuItem icon={<RedoIcon fontSize="small" />}>Redo</MenuItem>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuRoot>
</Menubar>
);
}
그룹 라벨 (Group labels)
메뉴 항목들을 라벨이 있는 그룹으로 묶어 논리적인 섹션으로 정리할 수 있어요.
import * as React from 'react';
import InfoIcon from '@mui/icons-material/Info';
import SettingsIcon from '@mui/icons-material/Settings';
import BuildIcon from '@mui/icons-material/Build';
import MonitorHeartIcon from '@mui/icons-material/MonitorHeart';
import TimelineIcon from '@mui/icons-material/Timeline';
import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
import ToggleOnIcon from '@mui/icons-material/ToggleOn';
import TuneIcon from '@mui/icons-material/Tune';
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
import VisibilityIcon from '@mui/icons-material/Visibility';
import UndoIcon from '@mui/icons-material/Undo';
import RedoIcon from '@mui/icons-material/Redo';
import ContentCutIcon from '@mui/icons-material/ContentCut';
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
import ContentPasteIcon from '@mui/icons-material/ContentPaste';
import {
Menubar,
MenuRoot,
MenuTrigger,
MenuPortal,
MenuPositioner,
MenuPopup,
MenuItem,
MenuSeparator,
MenuSubmenuRoot,
MenuSubmenuTrigger,
MenuGroup,
MenuGroupLabel,
} from './components/Menubar';
export default function GroupLabelMenubar() {
return (
<Menubar>
<MenuRoot>
<MenuTrigger>App</MenuTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4} alignOffset={-2}>
<MenuPopup>
<MenuGroup>
<MenuGroupLabel>General</MenuGroupLabel>
<MenuItem icon={<InfoIcon fontSize="small" />}>About</MenuItem>
<MenuItem icon={<SettingsIcon fontSize="small" />}>
Settings...
</MenuItem>
</MenuGroup>
<MenuSeparator />
<MenuSubmenuRoot>
<MenuSubmenuTrigger icon={<BuildIcon fontSize="small" />}>
Services
</MenuSubmenuTrigger>
<MenuPortal>
<MenuPositioner alignOffset={-4}>
<MenuPopup>
<MenuGroup>
<MenuGroupLabel>Development</MenuGroupLabel>
<MenuItem icon={<MonitorHeartIcon fontSize="small" />}>
Activity Monitor
</MenuItem>
<MenuItem icon={<TimelineIcon fontSize="small" />}>
System Trace
</MenuItem>
<MenuItem icon={<InsertDriveFileIcon fontSize="small" />}>
File Activity
</MenuItem>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuGroupLabel>Shortcuts</MenuGroupLabel>
<MenuItem icon={<ToggleOnIcon fontSize="small" />}>
Toggle Gate
</MenuItem>
<MenuItem icon={<TuneIcon fontSize="small" />}>
Services Settings...
</MenuItem>
</MenuGroup>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuSubmenuRoot>
<MenuSeparator />
<MenuGroup>
<MenuGroupLabel>Window</MenuGroupLabel>
<MenuItem icon={<VisibilityOffIcon fontSize="small" />}>
Hide App
</MenuItem>
<MenuItem icon={<VisibilityOffIcon fontSize="small" />}>
Hide Others
</MenuItem>
<MenuItem icon={<VisibilityIcon fontSize="small" />}>
Show All
</MenuItem>
</MenuGroup>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuRoot>
<MenuRoot>
<MenuTrigger>Edit</MenuTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4}>
<MenuPopup>
<MenuGroup>
<MenuGroupLabel>History</MenuGroupLabel>
<MenuItem icon={<UndoIcon fontSize="small" />}>Undo</MenuItem>
<MenuItem icon={<RedoIcon fontSize="small" />}>Redo</MenuItem>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuGroupLabel>Clipboard</MenuGroupLabel>
<MenuItem icon={<ContentCutIcon fontSize="small" />}>Cut</MenuItem>
<MenuItem icon={<ContentCopyIcon fontSize="small" />}>Copy</MenuItem>
<MenuItem icon={<ContentPasteIcon fontSize="small" />}>
Paste
</MenuItem>
</MenuGroup>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuRoot>
</Menubar>
);
}
Base UI API
모든 props에 대한 전체 참조는 아래 문서를 확인하세요.