You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Perry currently doesn't support adding custom menu bar items to the macOS app menu bar. Apps built with Perry get the default menu bar but have no way to add custom menus or menu items.
Use Case
When building a macOS app (e.g., a JSON viewer), it's common to expose actions like "Open File", "Paste from Clipboard", "Find", "Expand All", etc. through the menu bar. Currently the only way to trigger actions is via addKeyboardShortcut(), but there's no corresponding menu bar UI for discoverability.
Proposed API
Something like:
import{menuBarAddMenu,menuBarAddItem}from"perry/ui"// Create a top-level menuconstfileMenu=menuBarAddMenu("File")menuBarAddItem(fileMenu,"Open...","o",1,()=>{openFile()})menuBarAddItem(fileMenu,"Paste JSON","v",1,()=>{pasteJson()})constviewMenu=menuBarAddMenu("View")menuBarAddItem(viewMenu,"Expand All","1",1,()=>{expandAll()})menuBarAddItem(viewMenu,"Collapse All","2",1,()=>{collapseAll()})
This would allow Perry apps to have proper macOS menu bars with keyboard shortcut indicators, matching native app conventions.
Current Workaround
Using addKeyboardShortcut() for all actions and displaying keyboard hints in the app's UI (e.g., an about screen listing shortcuts). This works but isn't discoverable through the standard macOS menu bar.
Activity
proggeramlug commentedon Mar 2, 2026
This has now been implemented.
fix: cross-module await on Promise<[T, T]> tuple — indexing returned …
fix: chained arr.sort(cb).slice(0, N) corrupted to non-array (segfaul…
llvm-backend: fix try/catch state + error property access
llvm-backend: test_gap_array_methods MATCH — finish remaining 3 markers
llvm-backend: fix try/catch state + error property access
llvm-backend: test_gap_array_methods MATCH — finish remaining 3 markers
perf(runtime): #179 tier 1 #1 — block size 8 MB → 1 MB (v0.5.196)
feat(stdlib): web streams api (ReadableStream + WritableStream + Tran…
feat(harmonyos): Phase 2 v3 Option 1 — showToast bridge (drain queue …
feat(harmonyos): Phase 2 v3 Option 1 — showToast bridge (drain queue …
feat(harmonyos): Phase 2 v3 Option 1 — showToast bridge (drain queue …
fix(compile,codegen): #360 item #2 — process import resolution + cwd …
perf(codegen): #436 close image_convolution gap — strict-i32-bounded …
19 remaining items
fix(gc): root the ten unrooted runtime-side caches, and the scanner t…
fix(gc): root the ten unrooted runtime-side caches, and the scanner t…
feat(eh): invoke/landingpad try lowering behind PERRY_EH=invoke (#7302)
feat(eh)!: flip to invoke/landingpad, delete the setjmp lowering (#7302)
Exception lowering: setjmp/longjmp → LLVM invoke/landingpad (#7302) (#…
fix(native-backend): decline SEH funclets, refresh stale corpora, dro…
fix(gc): await polled a promise the event-loop pump had already moved (…
fix(runtime): hold #7983's shape stamp at plain objects — class insta…
fix(runtime): birth-stamp the class allocators #8009 left lazy, and g…
fix(object): a Buffer/DataView receiver must not reach the ordinary o…
fix(runtime): keep initializer addresses per-heap too
fix(runtime): make the path-module registry per-heap so one process c…
object model: enforce the three shape rules the single read path needs
object model: enforce the three shape rules the single read path needs
perf(runtime): stop the first setTimeout paying for the globalThis bo…