Murasaki
ガイド

アプリメニュー

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 が必要です。

murasaki.config.ts
window: {
  capabilities: [
    'menu:application',
    'window:close',
    'clipboard:readText',
    'clipboard:writeText',
  ],
}

native roleには対応するcapabilityも必要です。上のlistは、例に含まれる { role: 'close' } と完全な { role: 'editMenu' } submenuの両方を許可します。

メニューを宣言する

ルートレイアウトで一度だけ呼び出します。メニューは { label, items } のグループか、 標準の { role } サブメニューのいずれかです。各項目はカスタムエントリ、標準の { role }、または区切り線です:

src/app/layout.tsx
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
  • メニューロール: editMenuwindowMenu — 標準の Edit / Window サブメニューを 1 行で。

標準的なものにはロールを使い(特に Edit 項目 — copy/paste はフォーカス中の欄に届く ネイティブ挙動が必要です)、それ以外は action を持つカスタムエントリを使います。

custom application menuには常に menu:application が必要です。使用するnative roleに 応じて、次のcapabilityも追加します。

role追加で必要なcapability
quitapp:quit
closewindow:close
minimizewindow:minimize
zoomwindow:toggleMaximize
cut, copyclipboard:writeText
pasteclipboard:readText
editMenuclipboard:readTextclipboard:writeText の両方
windowMenuwindow:minimizewindow:toggleMaximize の両方
undo, redo, selectAll, reloadmenu: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 の代わりにサブメニュー
}

項目の形と actionuseContextMenu と 同じです。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 のクラシックなスタイルを引き継ぎ、 ダークモードには追従しません。close roleはsecondaryをhideして再open可能にし、 primaryの main closeとquitはapp lifecycleへ進みます。
  • Linux — デフォルトのメニューバーはまだありません。

次へ

GitHub でこのページを改善

On this page