Skip to content

fix(macos): convert Main.storyboard using programmatic AppKit APIs#2836

Draft
tido64 wants to merge 1 commit into
trunkfrom
tido/replace-storyboard
Draft

fix(macos): convert Main.storyboard using programmatic AppKit APIs#2836
tido64 wants to merge 1 commit into
trunkfrom
tido/replace-storyboard

Conversation

@tido64

@tido64 tido64 commented Jul 3, 2026

Copy link
Copy Markdown
Member

Description

Resolves #111.

Platforms affected

  • Android
  • iOS
  • macOS
  • visionOS
  • Windows

Test plan

cd packages/example-macos/
pod install --project-directory=macos
yarn macos

# In a separate terminal
yarn start

Screenshots

image

More below…

@github-actions github-actions Bot added platform: iOS This affects iOS platform: macOS This affects macOS platform: visionOS labels Jul 3, 2026

@tido64 tido64 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main menu screenshots 👇

Comment on lines +76 to +93
return NSMenuItem(submenu: title, items: [
NSMenuItem(title: "About \(title)", action: #selector(NSApplication.orderFrontStandardAboutPanel(_:))),
.separator(),
NSMenuItem(title: "Preferences…", keyEquivalent: ","),
.separator(),
NSMenuItem(submenu: servicesMenu),
.separator(),
NSMenuItem(title: "Hide \(title)", action: #selector(NSApplication.hide(_:)), keyEquivalent: "h"),
NSMenuItem(
title: "Hide Others",
action: #selector(NSApplication.hideOtherApplications(_:)),
keyEquivalent: "h",
keyEquivalentModifierMask: [.option, .command]
),
NSMenuItem(title: "Show All", action: #selector(NSApplication.unhideAllApplications(_:))),
.separator(),
NSMenuItem(title: "Quit \(title)", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q"),
])

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Comment on lines +97 to +116
NSMenuItem(submenu: "File", items: [
NSMenuItem(title: "New", action: #selector(NSDocumentController.newDocument(_:)), keyEquivalent: "n"),
NSMenuItem(title: "Open…", action: #selector(NSDocumentController.openDocument(_:)), keyEquivalent: "o"),
NSMenuItem(submenu: "Open Recent", items: [
NSMenuItem(title: "Clear Menu", action: #selector(NSDocumentController.clearRecentDocuments(_:))),
]),
.separator(),
NSMenuItem(title: "Close", action: #selector(NSWindow.performClose(_:)), keyEquivalent: "w"),
NSMenuItem(title: "Save…", action: #selector(NSDocument.save(_:)), keyEquivalent: "s"),
NSMenuItem(title: "Save As…", action: #selector(NSDocument.saveAs(_:)), keyEquivalent: "S"),
NSMenuItem(title: "Revert to Saved", action: #selector(NSDocument.revertToSaved(_:)), keyEquivalent: "r"),
.separator(),
NSMenuItem(
title: "Page Setup…",
action: #selector(NSDocument.runPageLayout(_:)),
keyEquivalent: "P",
keyEquivalentModifierMask: [.shift, .command]
),
NSMenuItem(title: "Print…", action: #selector(NSView.printView(_:)), keyEquivalent: "p"),
])

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Comment on lines +120 to +239
NSMenuItem(submenu: "Edit", items: [
NSMenuItem(title: "Undo", action: Selector(("undo:")), keyEquivalent: "z"),
NSMenuItem(title: "Redo", action: Selector(("redo:")), keyEquivalent: "Z"),
.separator(),
NSMenuItem(title: "Cut", action: #selector(NSText.cut(_:)), keyEquivalent: "x"),
NSMenuItem(title: "Copy", action: #selector(NSText.copy(_:)), keyEquivalent: "c"),
NSMenuItem(title: "Paste", action: #selector(NSText.paste(_:)), keyEquivalent: "v"),
NSMenuItem(
title: "Paste and Match Style",
action: #selector(NSTextView.pasteAsPlainText(_:)),
keyEquivalent: "V",
keyEquivalentModifierMask: [.option, .command]
),
NSMenuItem(title: "Delete", action: #selector(NSText.delete(_:))),
NSMenuItem(title: "Select All", action: #selector(NSText.selectAll(_:)), keyEquivalent: "a"),
.separator(),
NSMenuItem(submenu: "Find", items: [
NSMenuItem(
title: "Find…",
action: #selector(NSTextView.performFindPanelAction(_:)),
keyEquivalent: "f",
tag: 1
),
NSMenuItem(
title: "Find and Replace…",
action: #selector(NSTextView.performFindPanelAction(_:)),
keyEquivalent: "f",
keyEquivalentModifierMask: [.option, .command],
tag: 12
),
NSMenuItem(
title: "Find Next",
action: #selector(NSTextView.performFindPanelAction(_:)),
keyEquivalent: "g",
tag: 2
),
NSMenuItem(
title: "Find Previous",
action: #selector(NSTextView.performFindPanelAction(_:)),
keyEquivalent: "G",
tag: 3
),
NSMenuItem(
title: "Use Selection for Find",
action: #selector(NSTextView.performFindPanelAction(_:)),
keyEquivalent: "e",
tag: 7
),
NSMenuItem(
title: "Jump to Selection",
action: #selector(NSTextView.centerSelectionInVisibleArea(_:)),
keyEquivalent: "j"
),
]),
NSMenuItem(submenu: "Spelling and Grammar", items: [
NSMenuItem(
title: "Show Spelling and Grammar",
action: #selector(NSText.showGuessPanel(_:)),
keyEquivalent: ":"
),
NSMenuItem(
title: "Check Document Now",
action: #selector(NSText.checkSpelling(_:)),
keyEquivalent: ";"
),
.separator(),
NSMenuItem(
title: "Check Spelling While Typing",
action: #selector(NSTextView.toggleContinuousSpellChecking(_:))
),
NSMenuItem(
title: "Check Grammar With Spelling",
action: #selector(NSTextView.toggleGrammarChecking(_:))
),
NSMenuItem(
title: "Correct Spelling Automatically",
action: #selector(NSTextView.toggleAutomaticSpellingCorrection(_:))
),
]),
NSMenuItem(submenu: "Substitutions", items: [
NSMenuItem(
title: "Show Substitutions",
action: #selector(NSTextView.orderFrontSubstitutionsPanel(_:))
),
.separator(),
NSMenuItem(
title: "Smart Copy/Paste",
action: #selector(NSTextView.toggleSmartInsertDelete(_:))
),
NSMenuItem(
title: "Smart Quotes",
action: #selector(NSTextView.toggleAutomaticQuoteSubstitution(_:))
),
NSMenuItem(
title: "Smart Dashes",
action: #selector(NSTextView.toggleAutomaticDashSubstitution(_:))
),
NSMenuItem(
title: "Smart Links",
action: #selector(NSTextView.toggleAutomaticLinkDetection(_:))
),
NSMenuItem(
title: "Data Detectors",
action: #selector(NSTextView.toggleAutomaticDataDetection(_:))
),
NSMenuItem(
title: "Text Replacement",
action: #selector(NSTextView.toggleAutomaticTextReplacement(_:))
),
]),
NSMenuItem(submenu: "Transformations", items: [
NSMenuItem(title: "Make Upper Case", action: #selector(NSTextView.uppercaseWord(_:))),
NSMenuItem(title: "Make Lower Case", action: #selector(NSTextView.lowercaseWord(_:))),
NSMenuItem(title: "Capitalize", action: #selector(NSTextView.capitalizeWord(_:))),
]),
NSMenuItem(submenu: "Speech", items: [
NSMenuItem(title: "Start Speaking", action: #selector(NSTextView.startSpeaking(_:))),
NSMenuItem(title: "Stop Speaking", action: #selector(NSTextView.stopSpeaking(_:))),
]),
])

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Comment on lines +243 to +267
NSMenuItem(submenu: "View", items: [
NSMenuItem(
title: "Show Toolbar",
action: #selector(NSWindow.toggleToolbarShown(_:)),
keyEquivalent: "t",
keyEquivalentModifierMask: [.option, .command]
),
NSMenuItem(
title: "Customize Toolbar…",
action: #selector(NSWindow.runToolbarCustomizationPalette(_:))
),
.separator(),
NSMenuItem(
title: "Show Sidebar",
action: #selector(NSSplitViewController.toggleSidebar(_:)),
keyEquivalent: "s",
keyEquivalentModifierMask: [.control, .command]
),
NSMenuItem(
title: "Enter Full Screen",
action: #selector(NSWindow.toggleFullScreen(_:)),
keyEquivalent: "f",
keyEquivalentModifierMask: [.control, .command]
),
])

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

Comment on lines +271 to +298
let rememberLastComponentMenuItem = NSMenuItem(
title: "Remember Last Opened Component",
action: #selector(onRememberLastComponentSelected(_:)),
target: self
)
rememberLastComponentMenuItem.isEnabled = false
self.rememberLastComponentMenuItem = rememberLastComponentMenuItem

let reactMenu = NSMenu(title: "React", items: [
NSMenuItem(
title: "Load Embedded JS Bundle",
action: #selector(onLoadEmbeddedBundleSelected(_:)),
target: self
),
NSMenuItem(
title: "Load From Dev Server",
action: #selector(onLoadFromDevServerSelected(_:)),
target: self
),
rememberLastComponentMenuItem,
.separator(),
])
reactMenu.autoenablesItems = false
self.reactMenu = reactMenu

let reactMenuItem = NSMenuItem(submenu: reactMenu)
reactMenuItem.isHidden = true
return reactMenuItem

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Comment on lines +302 to +311
let windowMenu = NSMenu(title: "Window", items: [
NSMenuItem(title: "Minimize", action: #selector(NSWindow.performMiniaturize(_:)), keyEquivalent: "m"),
NSMenuItem(title: "Zoom", action: #selector(NSWindow.performZoom(_:))),
.separator(),
NSMenuItem(title: "Bring All to Front", action: #selector(NSApplication.arrangeInFront(_:))),
])

NSApp.windowsMenu = windowMenu

return NSMenuItem(submenu: windowMenu)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Comment on lines +315 to +321
let helpMenu = NSMenu(title: "Help", items: [
NSMenuItem(title: "\(title) Help", action: #selector(NSApplication.showHelp(_:)), keyEquivalent: "?"),
])

NSApp.helpMenu = helpMenu

return NSMenuItem(submenu: helpMenu)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

@tido64 tido64 force-pushed the tido/replace-storyboard branch from 1c22604 to 2298886 Compare July 3, 2026 12:07
@tido64 tido64 force-pushed the tido/replace-storyboard branch from 2298886 to c761fd2 Compare July 3, 2026 13:03
@Saadnajmi

Copy link
Copy Markdown
Collaborator

I think I have a WIP in RNM where I changed the remote to SwiftUI with much of the same fratutes. I can dig it up?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

macOS: Migrate to SwiftUI and deprecate Main.storyboard

2 participants