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.

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: openbegin_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.

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. 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_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: pinned to the row’s top-right and pulled back by the card’s own inset, so the child’s first row lines up with the row that opened it and the two cards touch. No gap on purpose — a strip of nothing between them is a strip the pointer crosses on its way in, and it would land on a sibling row and close what it was reaching for. Near the right edge the layer snaps rather than flipping; gpui’s anchored picks no sides.
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 + Retry affordance (the caller attaches the listener to the returned id).
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_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. 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
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]).
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.