Components / Menus & actions
Command palette
Markdown crates/ui/src/palette.rs docs.rs
use ui::palette::{self, CommandPalette, PaletteEvent};
palette::init(cx); // once, at startup, alongside input::init
let palette = cx.new(|cx| CommandPalette::new(COMMANDS.to_vec(), cx));
cx.subscribe(&palette, |_, _, event, _| match event {
PaletteEvent::Selected(index) => { /* run command `index` */ }
PaletteEvent::Dismissed => { /* unmount */ }
})
.detach();Indices are into the original item list, never into the filtered view — match on a filtered index and the first query you type runs the wrong command.
API
// ui::palette
/// Once at startup, alongside `input::init`.
pub fn init(cx: &mut App);
impl CommandPalette {
/// Owns a query, a filtered view and an active row.
pub fn new(items: Vec<SharedString>, cx: &mut Context<Self>) -> Self;
// ...
}
/// The host decides what a selection means.
pub enum PaletteEvent { Selected(usize), Dismissed }Keys are up/down, ctrl-p/ctrl-n, enter and escape, scoped to the palette's context — which wraps the query field's, so typing still reaches it. popover::Filter is the ranking underneath, shared with Combobox: prefix matches first, then substring, stable within each rank.
Mounting is the caller's — usually centred over a scrim, for which popover::modal_glass is the frame. Only text changes re-rank; moving the query caret preserves the highlighted command.