アプリメニュー
useAppMenu でネイティブのアプリケーションメニューバーを定義する — macOS では NSMenu、Windows では HMENU。
useAppMenu はアプリのメニューバー — macOS では画面上部のメニュー、Windows ではウィンドウのメニューバー — を宣言します。useContextMenuと同じく、マークアップではなくフックです。項目は Rust 側に投げられ、本物の OS メニュー(NSMenu / HMENU)が構築されます。Electron の Menu.setApplicationMenu や Tauri のメニュー API に相当する Murasaki の機能です。
これは オプトイン の機能です。呼ばなくても、アプリには Murasaki の標準メニュー(About / Quit を含むアプリケーションメニューに加えて Edit と Window)が付きます。独自のメニューにしたいときだけ useAppMenu を呼び出します。アプリケーションメニューはプロセス全体で共有されるため、置き換えられるのはプライマリの main レンダラーだけであり、そのレンダラーには menu:application が必要です。
window: {
capabilities: [
'menu:application',
'window:close',
'clipboard:readText',
'clipboard:writeText',
],
}ネイティブロールには、それぞれ対応するケイパビリティも必要です。上記のリストは、例に含まれる { role: 'close' } と、完全な { role: 'editMenu' } サブメニューの両方をカバーしています。
メニューを宣言する
ルートレイアウトで一度だけ呼び出します。メニューは { 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 を持つカスタムエントリを使います。
カスタムのアプリケーションメニューには常に menu:application が必要です。使用するネイティブロールに応じて、以下のケイパビリティも追加してください。
| ロール | 追加で必要なケイパビリティ |
|---|---|
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 以外は不要 |
必要なケイパビリティが1つでも欠けている場合、Murasaki は置き換え全体を拒否します。一部だけが動作するメニューをインストールせず、現在のアプリケーションメニューを維持します。
形
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 はプライマリレイアウトで一度だけマウントしてください。隠れたレンダラーがプロセス全体で共有されるネイティブ UI を置き換えてしまわないよう、セカンダリウィンドウからの呼び出しは無視されます。呼び出さなければ Murasaki のデフォルトメニューのままです。
プラットフォームメモ
- macOS — 画面上部の
NSMenu。アプリ名メニューが常に先頭に追加されます。 - Windows — ウィンドウ内の
HMENUバー。OS のクラシックなスタイルを引き継ぎ、ダークモードには追従しません。closeロールはセカンダリウィンドウでは非表示にするだけで再び開けるようにします。プライマリのmainウィンドウを閉じる操作とquitは、アプリのライフサイクル処理に進みます。 - Linux — ウィンドウ内の GTK メニューバー。Windows と同じシンプルな File / Edit / Window 構成で、macOS のような太字のアプリ名サブメニューはありません。Edit ロールの項目は、ネイティブのレスポンダーチェーンではなく、フォーカス中の WebView で
document.execCommandを実行します。