ui: Add submenus to ContextMenu (#45743)

This PR introduces submenu functionality for Zed's dropdown/context
menus.

<img width="600" height="830" alt="Screenshot 2025-12-27 at 2  03@2x"
src="https://github.com/user-attachments/assets/eadfcd74-07fe-4a1f-be76-11b547c16dc8"
/>

```rs
.submenu("Trigger", |menu, _, _| {
    menu.entry("Item…", None, |_, _| {})
        .entry("Item…", None, |_, _| {})
})
```

Release Notes:

- N/A

---------

Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com>
This commit is contained in:
Danilo Leal
2025-12-30 07:49:01 -03:00
committed by GitHub
parent 392b6184bf
commit 469ad070b0
6 changed files with 862 additions and 76 deletions

View File

@@ -55,6 +55,13 @@
"down": "menu::SelectNext", "down": "menu::SelectNext",
}, },
}, },
{
"context": "menu",
"bindings": {
"right": "menu::SelectChild",
"left": "menu::SelectParent",
},
},
{ {
"context": "Editor", "context": "Editor",
"bindings": { "bindings": {

View File

@@ -54,6 +54,13 @@
"ctrl-cmd-s": "workspace::ToggleWorktreeSecurity", "ctrl-cmd-s": "workspace::ToggleWorktreeSecurity",
}, },
}, },
{
"context": "menu",
"bindings": {
"right": "menu::SelectChild",
"left": "menu::SelectParent",
},
},
{ {
"context": "Editor", "context": "Editor",
"use_key_equivalents": true, "use_key_equivalents": true,

View File

@@ -54,6 +54,13 @@
"down": "menu::SelectNext", "down": "menu::SelectNext",
}, },
}, },
{
"context": "menu",
"bindings": {
"right": "menu::SelectChild",
"left": "menu::SelectParent",
},
},
{ {
"context": "Editor", "context": "Editor",
"use_key_equivalents": true, "use_key_equivalents": true,

View File

@@ -26,6 +26,10 @@ actions!(
SelectFirst, SelectFirst,
/// Selects the last item in the menu. /// Selects the last item in the menu.
SelectLast, SelectLast,
/// Enters a submenu (navigates to child menu).
SelectChild,
/// Exits a submenu (navigates to parent menu).
SelectParent,
/// Restarts the menu from the beginning. /// Restarts the menu from the beginning.
Restart, Restart,
EndSlot, EndSlot,

File diff suppressed because it is too large Load Diff

View File

@@ -247,6 +247,30 @@ impl Component for DropdownMenu {
.entry("Option 4", None, |_, _| {}) .entry("Option 4", None, |_, _| {})
}); });
let menu_with_submenu = ContextMenu::build(window, cx, |this, _, _| {
this.entry("Toggle All Docks", None, |_, _| {})
.submenu("Editor Layout", |menu, _, _| {
menu.entry("Split Up", None, |_, _| {})
.entry("Split Down", None, |_, _| {})
.separator()
.entry("Split Side", None, |_, _| {})
})
.separator()
.entry("Project Panel", None, |_, _| {})
.entry("Outline Panel", None, |_, _| {})
.separator()
.submenu("Autofill", |menu, _, _| {
menu.entry("Contact…", None, |_, _| {})
.entry("Passwords…", None, |_, _| {})
})
.submenu_with_icon("Predict", IconName::ZedPredict, |menu, _, _| {
menu.entry("Everywhere", None, |_, _| {})
.entry("At Cursor", None, |_, _| {})
.entry("Over Here", None, |_, _| {})
.entry("Over There", None, |_, _| {})
})
});
Some( Some(
v_flex() v_flex()
.gap_6() .gap_6()
@@ -271,6 +295,14 @@ impl Component for DropdownMenu {
), ),
], ],
), ),
example_group_with_title(
"Submenus",
vec![single_example(
"With Submenus",
DropdownMenu::new("submenu", "Submenu", menu_with_submenu)
.into_any_element(),
)],
),
example_group_with_title( example_group_with_title(
"Styles", "Styles",
vec![ vec![