Skip to main content

Module popover

Module popover 

Source
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::Submenu row 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_out plays: open → begin_close (render keeps mounting, with the out animation and dead hit-testing) → reap_popup’s timer finish_closees ~motion::MENU_OUT later. Use Self::is_open for logic (a closing popup already reads as closed) and Self::get / Self::is_closing for 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 sheet slides 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 be relative(), as for every anchored_menu_* variant. Plays menu-in (0.14s fade + 2px drop); closing (the Popup exit phase) swaps in menu-out. Dismissal is the caller’s .on_mouse_down_out on 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_menu opening UPWARD from the trigger (composer pickers, the user menu — anything anchored near the window bottom; Radix flips these automatically, gpui’s anchored needs 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_above right-aligned to the trigger’s right edge (t3code ComboboxPopup align="end" — right-side triggers like the composer’s ref picker open leftward instead of running off the window).
anchored_menu_below
anchored_menu opening 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_below right-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_below with 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::Submenu row drops, mounted on that row — which must be relative(). Its first row lines up with the row that opened it, and the two cards touch on whichever side submenu::place put it. chain is 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]), mirroring Theme::band, for the several callers with no Theme/cx in scope (some outside this crate’s ui module tree — threading a &Theme param would ripple past this task’s file scope).
classify_key
close_popup
Begin a popup’s exit phase and schedule its reap — Popup::begin_close and reap_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 popup on a press outside el — the card side of the pair menu_trigger completes.
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 of key_hint/key_hint_pair and 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: 0 prefix match, 1 substring, None no 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_menu so 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, unlike divider’s mx-1).
menu_step
Step the active row of a menu: wraps at both ends; None enters at the edge matching the direction. Empty menus stay None.
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_trigger for one popup shared by several triggers (a Popup<Menu> with a row’s index inside it): owns says whether the open popup is this trigger’s, so pressing another trigger switches menus instead of swallowing the press. See Popup::note_trigger_press_matching.
modal
Full-window modal: dim scrim + centered card with the dialog-in entrance. The scrim swallows clicks; the caller wires its own dismiss/confirm. Binds no keys, escape included. viewport is the window size (an anchored layer sizes to its children, so the scrim needs explicit dimensions). The frost radius matches dialog_card’s 16px rounding. on_dismiss is the scrim press. It is a parameter rather than the caller’s .on_mouse_down_out, for the same reason sheet’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
modal for 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.glass on it paints contents only, and the fill, hairline and shadow are the surface’s it is mounted on.
popover_card_flush
popover_card without the p-1 inset — 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. popup re-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 — modal pinned to an edge. It slides in over motion::DIALOG_IN and, once the caller’s Popup enters its exit phase, back out over motion::MENU_OUT — which it must, because Popup::finish_close reaps 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_trigger on its own, for a trigger whose open is more than Popup::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 with Popup::take_press_was_open.
trigger_press_matching
trigger_press for one popup shared by several triggers — see menu_trigger_matching.