Expand description
Popover / menu primitives: an anchored floating layer with the menu-in
animation, outside-click dismissal, and pure keyboard-navigation + search
reducers shared by every picker and menu (feature-inventory §1.12 popovers).
gpui pattern (examples/popover.rs at the pinned rev): the trigger element
conditionally children a deferred(anchored().child(content)) — deferred
paints on a floating layer above everything, anchored positions it relative
to the trigger (or an explicit point for context menus).
Pure logic (wrap-around list navigation, ranked substring filtering, key classification) lives in free functions with unit tests; the elements only feed them measurements/events.
Re-exports§
pub use submenu::Chain;
Modules§
- submenu
- Where the panel a
crate::menu::Item::Submenurow drops goes: beside the card that dropped it, on whichever side the window has room for.
Structs§
- Filter
- The state behind a searchable list: the items, the ranked view of them, and which row of that view is active. Shared by every picker — the palette, the combobox — so the mapping below is written and tested once.
- Popup
- Popup state with an exit phase. gpui unmounts an element the frame its
state drops, so a closing animation needs the state held alive while
motion::menu_outplays:open→begin_close(render keeps mounting, with the out animation and dead hit-testing) →reap_popup’s timerfinish_closees ~motion::MENU_OUTlater. UseSelf::is_openfor logic (a closing popup already reads as closed) andSelf::get/Self::is_closingfor rendering.
Enums§
- Loadable
- One async-loaded slot:
Idle(never requested) →Loading(skeletons) →Ready/Error(inline message + Retry). - MenuKey
- Keys the pickers care about, classified from a raw keystroke.
- Side
- Which edge a
sheetslides in from.
Constants§
- MENU_
ROW_ INSET - How far a
menu_row’s text sits in from its own edge. Content that is not a row lines up with the rows’ text by insetting this much.
Functions§
- anchored_
menu - Wrap popover content in a floating anchored layer attached to the trigger:
the caller
.child(anchored_menu(...))s this from the trigger element while open. The trigger must berelative(), as for everyanchored_menu_*variant. Playsmenu-in(0.14s fade + 2px drop);closing(thePopupexit phase) swaps inmenu-out. Dismissal is the caller’s.on_mouse_down_outon the content. The layer.occlude()s: hitboxes are paint-order only in gpui, so without it clicks on menu rows would ALSO fire whatever clickable sits under the floating layer. - anchored_
menu_ above anchored_menuopening UPWARD from the trigger (composer pickers, the user menu — anything anchored near the window bottom; Radix flips these automatically, gpui’sanchoredneeds the side picked).- anchored_
menu_ above_ at - Open an upward menu at a point inside a relative trigger. Useful for text completions, whose natural anchor is the token/caret rather than the input element’s outer edge.
- anchored_
menu_ above_ end anchored_menu_aboveright-aligned to the trigger’s right edge (t3code ComboboxPopupalign="end"— right-side triggers like the composer’s ref picker open leftward instead of running off the window).- anchored_
menu_ below anchored_menuopening DOWNWARD from the trigger’s bottom edge — a dropdown proper (the sidebar’s space filter). The default variant pins to the trigger’s top-left, which reads fine for context-style menus but covers a button-shaped trigger.- anchored_
menu_ below_ end anchored_menu_belowright-aligned to the trigger’s right edge — a row whose menu is opened from a control at its end, so the card drops from that control and opens inward rather than off the trigger’s far side.- anchored_
menu_ below_ gap anchored_menu_belowwith a caller-chosen trigger→card gap — the changes-header dropdowns hang off a tight titlebar band and need more breathing room than the default 6px (user report; t3code sits near 10).- anchored_
submenu - The panel a
crate::menu::Item::Submenurow drops, mounted on that row — which must berelative(). Its first row lines up with the row that opened it, and the two cards touch on whichever sidesubmenu::placeput it.chainis the open menu’s, shared by every panel in it. - band
- The recessed band tone for a palette/picker header or footer strip — a
translucent black so the glass still reads through (the add-space palette
converged on this; measured subtler tones vanish against the dim scrim).
Free function (like
ink/[hairline]/[wash]), mirroringTheme::band, for the several callers with noTheme/cxin scope (some outside this crate’suimodule tree — threading a&Themeparam would ripple past this task’s file scope). - classify_
key - close_
popup - Begin a popup’s exit phase and schedule its reap —
Popup::begin_closeandreap_popup, which are only ever correct together. A popup already closing or closed is left alone. - dialog_
body - Dialog body copy:
leading-relaxed text-muted-foreground. - dialog_
card - The centered dialog card (
dialog-pop):w-[360px] rounded-2xl border border-white/[0.1] bg-popover/95 p-5 shadow-2xl— popover tone ≈ #101010. - dialog_
field - Dialog text-field frame:
rounded-lg border border-white/[0.08] bg-white/[0.04] px-3 py-2. - dialog_
title - Dialog title.
- dismiss_
on_ out - Dismiss
popupon a press outsideel— the card side of the pairmenu_triggercompletes. - divider
- Hairline divider between menu sections (the reference
MenuSeparator:mx-1 my-1 h-px bg-white/[0.07]). - error_
row - Inline error row. A retry control is the caller’s child.
- filter_
indices - Filter + rank labels for a search query: prefix matches first, then
substring matches, stable within each rank. Returns indices into
labels. - kbd_
hint - A muted kbd hint chip inside menu rows (
⌘↵-style accelerators). - key_cap
- One footer key-cap (22px, rounded-5,
white/[0.05]) holding arbitrary children — the base ofkey_hint/key_hint_pairand the search-bar chips (“⌘K”, “esc”). - key_
hint - A footer legend: one icon key-cap + tiny verb (the add-space palette’s footer voice, shared by the pickers).
- key_
hint_ pair - A footer legend whose cap holds TWO glyphs split by a hairline (“[ ↑ | ↓ ] Navigate”) sharing one verb.
- key_
hint_ text - A footer legend whose cap holds a WORD (“tab”, “esc”) instead of a glyph — for keys with no icon in the set.
- match_
rank - Match rank of a label against a query:
0prefix match,1substring,Noneno match. Case-insensitive; an empty query matches everything at rank 1 (input order preserved). - menu_at
- A floating menu at an explicit window position (context menus). Occludes
like
anchored_menuso row clicks never reach elements underneath. - menu_
heading - Small uppercase section heading inside a floating menu (the reference
MenuHeading):px-2 pb-1 pt-1.5 uppercase tracking-[0.1em] text-muted-foreground/60. gpui has no letter-spacing at the pinned rev; the tracking is approximated with hair spaces. - menu_
note - A line of plain text in a menu — see
crate::menu::Item::Note. - menu_
row - One menu row (the reference
menuItem):gap-2.5 rounded-lg px-2 py-1.5, active =bg-white/10 text-foreground. The caller adds the id/click listener. - menu_
section - A bordered trailing menu section (the reference picker action groups /
branch-picker worktree block:
mt-1 flex flex-col gap-0.5 border-t border-white/[0.06] pt-1— the hairline runs edge-to-edge of the card’s p-1 inset, unlikedivider’s mx-1). - menu_
step - Step the active row of a menu: wraps at both ends;
Noneenters at the edge matching the direction. Empty menus stayNone. - menu_
trigger - Wire a trigger to the popup it toggles: press note on the way down, open or close on the way up.
- menu_
trigger_ matching menu_triggerfor one popup shared by several triggers (aPopup<Menu>with a row’s index inside it):ownssays whether the open popup is this trigger’s, so pressing another trigger switches menus instead of swallowing the press. SeePopup::note_trigger_press_matching.- modal
- Full-window modal: dim scrim + centered card with the
dialog-inentrance. The scrim swallows clicks; the caller wires its own dismiss/confirm. Binds no keys,escapeincluded.viewportis the window size (ananchoredlayer sizes to its children, so the scrim needs explicit dimensions). The frost radius matchesdialog_card’s 16px rounding.on_dismissis the scrim press. It is a parameter rather than the caller’s.on_mouse_down_out, for the same reasonsheet’s is: the scrim lives inside this deferred layer, so nothing outside can reach it. Without it a dialog could not be dismissed by clicking away from it by any caller — which is how this one shipped, and what it looked like was a dialog that only closed on its own buttons. - modal_
glass modalfor glass-tinted cards (the add-space palette): a LIGHTER scrim, so the material card reads like the popovers — the standard 0.6 dim buried the backdrop hue under the blur and the palette came out a flat grey slab next to the hue-inheriting menus (user report).- popover_
card - The floating-menu card. With
theme.glasson it paints contents only, and the fill, hairline and shadow are the surface’s it is mounted on. - popover_
card_ flush popover_cardwithout thep-1inset — for popovers that manage their own internal panes (the harness/model picker’s rail + list split).- reap_
popup - Schedule the reap for a
Popup::begin_close: after the exit animation’s span, drop the popup state and repaint.popupre-borrows the field from the view (the state can’t be captured — the view owns it). - redacted_
rows - Pulsing skeleton rows shown while a list loads (the reference:
h-7 animate-pulse rounded-md bg-white/[0.04]). Each row enters the wave after the one above it. - search_
line - The query line at the top of a picker popover: a magnifier, the field, and a hairline under it.
- sheet
- A panel over a dim scrim —
modalpinned to an edge. It slides in overmotion::DIALOG_INand, once the caller’sPopupenters its exit phase, back out overmotion::MENU_OUT— which it must, becausePopup::finish_closereaps on that spec’s span. - sheet_
panel - The panel body of a
sheet: glass card chrome rounded and hairlined on its inner edge only — the corners against the window edge are off-screen — so it reads as pulled out of the window rather than floating near it. - tracked_
upper - Uppercase + hair-space tracking (see
menu_heading). - trigger_
press - The press half of
menu_triggeron its own, for a trigger whose open is more thanPopup::open— a combobox that clears its query and focuses it, a gutter handle whose menu belongs to the release of a possible drag. The click side is then the caller’s, and reads the note withPopup::take_press_was_open. - trigger_
press_ matching trigger_pressfor one popup shared by several triggers — seemenu_trigger_matching.