iced-cube

Navigation

Command

A searchable list of actions, grouped, with icons and shortcut hints.

use iced_cube::navigation::command::{self, Output, State, command, group, item};
API reference
Inline: Grouped actions with icons, shortcut hints, keywords and a disabled row.Inline: Grouped actions with icons, shortcut hints, keywords and a disabled row.
Static preview
Inline. Grouped actions with icons, shortcut hints, keywords and a disabled row.

Usage

A command list puts every action behind one search field. Typing ranks the items within each group: an exact match comes first, then prefixes, then matches at the start of a word, then anywhere, then letters in order. Groups keep their order, and the highlight goes to the best match in any group, so Enter runs what was typed for. Keywords let an item be found by other names, such as “preferences” for Settings. Disabled items stay visible but are skipped by the keyboard.

The list is embedded where you place it. For an app-wide launcher, use the command palette, which builds this list into a dialog with the Ctrl+K and Ctrl+Shift+P chords, recent commands and nested pages. To compose one yourself, put the list in a dialog and open it from a button or a shortcut such as Ctrl+K, as the palette example does. Let that shortcut through the dialog with .pass_through(...) so it closes the palette too, and close the dialog when update returns Output::Activated or Output::Closed. Give a palette .max_height(...) rather than a fixed height, so it shrinks around a handful of matches instead of leaving an empty panel.

Results can also come from background work, such as a file index or a server. When update returns Output::Search(query), start a producer with that query and a clone of the sender. It sends command::results(query, group, items) as matches arrive; anything tagged with an older query is dropped, so slow searches never overwrite newer ones. The async example waits with futures-timer rather than a thread, so it runs in the browser too.

While the search field has focus, the list handles its keys itself, before a surrounding dialog or popover sees them. Home and End then move the highlight rather than the text cursor. Escape clears the query, and a second press returns Output::Closed.

The highlighted row is always the target of Enter, but it is only drawn highlighted while the field has focus or after the user moves the highlight with the keys or the pointer. An inline list in a sidebar therefore sits quietly until someone uses it. The widget reports focus changes with Event::Focus, so route every event to update.

Examples

Keyboard shortcuts

The default keymap with Ctrl+N and Ctrl+P added. The list handles keys while its field has focus; the app routes the rest through keys::subscription.

Keyboard shortcuts: The default keymap with Ctrl+N and Ctrl+P added. The list handles keys while its field has focus; the app routes the rest through keys::subscription.Keyboard shortcuts: The default keymap with Ctrl+N and Ctrl+P added. The list handles keys while its field has focus; the app routes the rest through keys::subscription.
Static preview

Async results

A background task streams file matches through the channel, tagged with their query. It waits with futures-timer, so it also runs in the browser.

Command palette

The list in a dialog, opened by a button or Ctrl+K. Escape clears the query, then closes the palette; Ctrl+K passes through the dialog to close it too.

Command palette: The list in a dialog, opened by a button or Ctrl+K. Escape clears the query, then closes the palette; Ctrl+K passes through the dialog to close it too.Command palette: The list in a dialog, opened by a button or Ctrl+K. Escape clears the query, then closes the palette; Ctrl+K passes through the dialog to close it too.
Static preview

API

ItemDescription
State::new(groups)Holds the groups of items and highlights the first enabled one.
group(label, items)Items under a heading. An empty label shows no heading.
item(id, label)Creates an item. Add .icon(glyph), .shortcut(text), .keywords([...]), .disabled(true) or .destructive(true).
.with_visible_rows(n)How many rows show at once (eight by default). The window follows the highlight and scrolls with the wheel.
state.update(Event)Handles typing, moving, activating, closing and results from the channel. Returns an Output.
OutputReady(sender) once the channel is open, Search(query) when the query changes, Activated(id) when an item is chosen, and Closed on Escape with an empty query.
state.results() / state.highlighted() / state.query()The ranked results with their group labels, the highlighted item and the current query.
state.shows_highlight() / state.is_focused()Whether the highlighted row is drawn highlighted, which it is while the field has focus or once the user has moved the highlight, and whether the field has focus.
command::score(query, text)The matcher: case-insensitive, in-order letters, preferring exact matches, prefixes and word starts. None when there is no match.
command::subscription()Owns the results channel. Emits Ready(sender) once, then batches of up to BATCH_SIZE (32).
command::results(query, group, items)What a producer sends. Results for any query but the current one are dropped, and the rest are shown in arrival order under their group.
command(&state)Renders the search field and results. It renders disabled until .on_event is set.
.on_event(f) / .placeholder(text) / .empty(text)Maps events to your message, and sets the field and empty-state text.
.loading(bool)Shows "Searching..." while a background search is running.
.width(length) / .height(length) / .id(id)The width fills by default. A fixed height stops the list resizing as results change.
.max_height(f32)Caps the height while the list still shrinks to fit a few results, as a palette should. Keep with_visible_rows within the cap, since rows past it are clipped.
.keymap(keymap)Replaces the default keymap. The list resolves its own key presses while its search field has focus.
command::default_keymap()The default shortcuts as a Keymap<Action>. Bind, unbind or clear chords to change them.
action.event(&state)Turns an Action into the Event it sends, or None when it would do nothing, for keys the app routes itself.

Keyboard

Default shortcuts. Every one can be changed or removed with a keymap; see Keyboard shortcuts.

KeysAction
ArrowDownNext Highlights the next enabled result, wrapping at the end.
ArrowUpPrevious Highlights the previous enabled result, wrapping at the start.
HomeFirst Highlights the first enabled result.
EndLast Highlights the last enabled result.
EnterActivate Activates the highlighted result.
EscapeClose Clears the query, or closes the list when the query is empty.
Esc