diff --git a/docs/api/menu-item.md b/docs/api/menu-item.md
index 8ee760d1cb44..980b27d2dee3 100644
--- a/docs/api/menu-item.md
+++ b/docs/api/menu-item.md
@@ -20,8 +20,14 @@ See [`Menu`](menu.md) for examples.
* `event` [KeyboardEvent](structures/keyboard-event.md)
* `role` string (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `toggleSpellChecker`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `showSubstitutions`, `toggleSmartQuotes`, `toggleSmartDashes`, `toggleTextReplacement`, `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `showAllTabs`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
`click` property will be ignored. See [roles](#roles).
- * `type` string (optional) - Can be `normal`, `separator`, `submenu`, `checkbox` or
- `radio`.
+ * `type` string (optional)
+ * `normal`
+ * `separator`
+ * `submenu`
+ * `checkbox`
+ * `radio`
+ * `header` - Only available on macOS 14 and up.
+ * `palette` - Only available on macOS 14 and up.
* `label` string (optional)
* `sublabel` string (optional) _macOS_ - Available in macOS >= 14.4
* `toolTip` string (optional) _macOS_ - Hover text for this menu item.
@@ -162,7 +168,10 @@ item's submenu, if present.
#### `menuItem.type`
-A `string` indicating the type of the item. Can be `normal`, `separator`, `submenu`, `checkbox` or `radio`.
+A `string` indicating the type of the item. Can be `normal`, `separator`, `submenu`, `checkbox`, `radio`, `header` or `palette`.
+
+> [!NOTE]
+> `header` and `palette` are only available on macOS 14 and up.
#### `menuItem.role`
diff --git a/lib/browser/api/menu-item.ts b/lib/browser/api/menu-item.ts
index 1ff4836caf30..6c58a80d33c6 100644
--- a/lib/browser/api/menu-item.ts
+++ b/lib/browser/api/menu-item.ts
@@ -71,7 +71,7 @@ const MenuItem = function (this: any, options: any) {
};
};
-MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio'];
+MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio', 'header', 'palette'];
MenuItem.prototype.getDefaultRoleAccelerator = function () {
return roles.getDefaultAccelerator(this.role);
diff --git a/lib/browser/api/menu.ts b/lib/browser/api/menu.ts
index 8e0a63f76465..10cad67f10c4 100644
--- a/lib/browser/api/menu.ts
+++ b/lib/browser/api/menu.ts
@@ -143,6 +143,9 @@ Menu.prototype.insert = function (pos, item) {
if (item.toolTip) this.setToolTip(pos, item.toolTip);
if (item.icon) this.setIcon(pos, item.icon);
if (item.role) this.setRole(pos, item.role);
+ if (item.type === 'palette' || item.type === 'header') {
+ this.setCustomType(pos, item.type);
+ }
// Make menu accessible to items.
item.overrideReadOnlyProperty('menu', this);
@@ -264,9 +267,11 @@ function removeExtraSeparators (items: (MenuItemConstructorOptions | MenuItem)[]
function insertItemByType (this: MenuType, item: MenuItem, pos: number) {
const types = {
normal: () => this.insertItem(pos, item.commandId, item.label),
+ header: () => this.insertItem(pos, item.commandId, item.label),
checkbox: () => this.insertCheckItem(pos, item.commandId, item.label),
separator: () => this.insertSeparator(pos),
submenu: () => this.insertSubMenu(pos, item.commandId, item.label, item.submenu),
+ palette: () => this.insertSubMenu(pos, item.commandId, item.label, item.submenu),
radio: () => {
// Grouping radio menu items
item.overrideReadOnlyProperty('groupId', generateGroupId(this.items, pos));
diff --git a/shell/browser/api/electron_api_menu.cc b/shell/browser/api/electron_api_menu.cc
index 595a3513c499..da093a8f4002 100644
--- a/shell/browser/api/electron_api_menu.cc
+++ b/shell/browser/api/electron_api_menu.cc
@@ -213,6 +213,10 @@ void Menu::SetRole(int index, const std::u16string& role) {
model_->SetRole(index, role);
}
+void Menu::SetCustomType(int index, const std::u16string& customType) {
+ model_->SetCustomType(index, customType);
+}
+
void Menu::Clear() {
model_->Clear();
}
@@ -286,6 +290,7 @@ void Menu::FillObjectTemplate(v8::Isolate* isolate,
.SetMethod("setSublabel", &Menu::SetSublabel)
.SetMethod("setToolTip", &Menu::SetToolTip)
.SetMethod("setRole", &Menu::SetRole)
+ .SetMethod("setCustomType", &Menu::SetCustomType)
.SetMethod("clear", &Menu::Clear)
.SetMethod("getIndexOfCommandId", &Menu::GetIndexOfCommandId)
.SetMethod("getItemCount", &Menu::GetItemCount)
diff --git a/shell/browser/api/electron_api_menu.h b/shell/browser/api/electron_api_menu.h
index 6b5ee0635da3..06fb805c06da 100644
--- a/shell/browser/api/electron_api_menu.h
+++ b/shell/browser/api/electron_api_menu.h
@@ -116,6 +116,7 @@ class Menu : public gin::Wrappable