アプリメニュー
useAppMenu でネイティブのアプリケーションメニューバーを定義する — macOS では NSMenu、Windows では HMENU。
useAppMenu はアプリのメニューバー — macOS では画面上部のメニュー、Windows では
ウィンドウのメニューバー — を宣言します。useContextMenu
と同じく、マークアップではなくフックです。項目は Rust 側に投げられ、本物の OS メニュー
(NSMenu / HMENU)が構築されます。Electron の Menu.setApplicationMenu や
Tauri のメニュー API に相当する Murasaki の機能です。
これは opt-in です。呼ばなくても、アプリには Murasaki の標準メニュー(About/Quit
を持つアプリメニュー + Edit + Window)が付きます。独自のメニューが欲しいときだけ
useAppMenu を呼びます。application menuはprocess-globalなのでprimary main renderer
だけが差し替えでき、そのrendererへ menu:application が必要です。
window: {
capabilities: [
'menu:application',
'window:close',
'clipboard:readText',
'clipboard:writeText',
],
}native roleには対応するcapabilityも必要です。上のlistは、例に含まれる
{ role: 'close' } と完全な { role: 'editMenu' } submenuの両方を許可します。
メニューを宣言する
ルートレイアウトで一度だけ呼び出します。メニューは { label, items } のグループか、
標準の { role } サブメニューのいずれかです。各項目はカスタムエントリ、標準の
{ role }、または区切り線です:
import { useAppMenu, Action } from 'murasaki'
useAppMenu([
{
label: 'File',
items: [
{ label: 'New Window', shortcut: 'command,N', action: () => openWindow() },
{ separator: true },
{ role: 'close' },
],
},
{ role: 'editMenu' },
{
label: 'View',
items: [{ label: 'Reload', shortcut: 'command,R', action: <Action.Reload /> }],
},
])macOS では標準のアプリ名メニュー(About / Hide / Quit)が常にあなたのメニューの前に
追加されるので、Cmd+Q などはそのまま機能します — 自分で宣言する必要はありません。
ロール
role は標準の項目やサブメニューを取り込みます。ローカライズ済みで、ネイティブの
挙動(macOS では NSMenu のレスポンダチェーン)に配線されるため、action を渡す
必要はありません。
- 項目ロール:
quit,close,minimize,zoom,undo,redo,cut,copy,paste,selectAll,reload。 - メニューロール:
editMenuとwindowMenu— 標準の Edit / Window サブメニューを 1 行で。
標準的なものにはロールを使い(特に Edit 項目 — copy/paste はフォーカス中の欄に届く
ネイティブ挙動が必要です)、それ以外は action を持つカスタムエントリを使います。
custom application menuには常に menu:application が必要です。使用するnative roleに
応じて、次のcapabilityも追加します。
| role | 追加で必要なcapability |
|---|---|
quit | app:quit |
close | window:close |
minimize | window:minimize |
zoom | window:toggleMaximize |
cut, copy | clipboard:writeText |
paste | clipboard:readText |
editMenu | clipboard:readText と clipboard:writeText の両方 |
windowMenu | window:minimize と window:toggleMaximize の両方 |
undo, redo, selectAll, reload | menu:application 以外は不要 |
必要なcapabilityが1つでも欠けている場合、Murasakiは置換全体を拒否します。一部だけが 動くmenuをinstallせず、現在のapplication menuを維持します。
形
type AppMenu =
| { label: string; items: AppMenuItemSpec[] }
| { role: 'editMenu' | 'windowMenu' }
type AppMenuItemSpec = AppMenuEntry | { role: AppMenuItemRole } | { separator: true }
interface AppMenuEntry {
label: string
shortcut?: string // 例: "command,N"
disabled?: boolean
action?: AppMenuAction // 組み込みの <Action.*/> 要素、または関数
items?: AppMenuItemSpec[] // action の代わりにサブメニュー
}項目の形と action は useContextMenu と
同じです。action は自作の関数か組み込みの <Action.*/>、shortcut はネイティブの
アクセラレータラベルを設定します。アプリのアクションは
createActions
で再利用できます。
useAppMenu はprimary layoutで一度だけmountします。hidden rendererがprocess-global
native chromeを置換しないよう、secondary windowからのcallは無視されます。呼ばなければ
Murasakiのdefault menuのままです。
プラットフォームメモ
- macOS — 画面上部の
NSMenu。アプリ名メニューが常に先頭に追加されます。 - Windows — ウィンドウ内の
HMENUバー。OS のクラシックなスタイルを引き継ぎ、 ダークモードには追従しません。closeroleはsecondaryをhideして再open可能にし、 primaryのmaincloseとquitはapp lifecycleへ進みます。 - Linux — デフォルトのメニューバーはまだありません。