Combobox
Autocomplete input and command palette with a list of suggestions.
Overview
输入过滤 + 点击/Enter 选中;选中后 label 回填并可继续输入重新搜索。
Installation
Combobox 是单个 Rust 文件(src/combobox.rs)—— 文本编辑复用 gpui-base 的 InputState,弹出层语义(role/ARIA/焦点移交)来自 gpui-base::Combobox 原语,勾选与 chevron 用 PathBuilder 手绘。
[dependencies]gpui-kit = "0.6.6"# combobox.rs builds on gpui-base primitives:# InputState (editing) + Combobox root (role/ARIA# + popup semantics) — no extra deps.# Download the runnable example crate, then:cargo run --locked -- --combobox# Other demos:cargo run --locked -- --combobox multiplecargo run --locked -- --combobox groupscargo run --locked -- --combobox disabledUsage
Combobox 是实体:输入框是一个真实的 InputState(先 new 出来再传进构造器),实体自持过滤列表、active 行和选中值。输入即过滤(label/value/group 子串匹配),Enter 提交高亮行,选项回填 label 后再次输入即可重新搜索。
use justdo_command::combobox::{Combobox, ComboboxItem, ComboboxChangeEvent};use gpui_kit::base::input::InputState;// The input entity is created with a Window, then the// combobox entity wraps it and owns selection + filtering.let input = cx.new(|cx| { InputState::new(window, cx).placeholder("Select framework…")});let combobox = cx.new(|cx| { Combobox::new(input, cx) .items(vec![ ComboboxItem::new("Next.js"), ComboboxItem::new("SvelteKit"), ComboboxItem::new("Astro").disabled(true), ]) .empty_text("No framework found.")});cx.subscribe(&combobox, |view, _, ev: &ComboboxChangeEvent, cx| { view.selection = ev.selected.clone(); cx.notify();});div().child(combobox)网页预览与桌面端运行同一份 Rust / GPUI 组件。
Composition
结构对应 Combobox → Input + Listbox:field 行承载 chips/清空/开合,popup 列表渲染分组、勾选与禁用态。
Combobox entity — input + popup + selection├── input Entity<InputState> — real text editing (gpui-base)├── field InputBase — chips / ✕ clear / chevron trigger row├── popup filtered rows — active highlight, ✓ on selected│ ├── group headers ComboboxItem::group(..)│ ├── hint ComboboxItem::hint(..) — trailing quiet text│ └── empty .empty_text(..) — ComboboxEmpty├── single .default_value(..) — label refills the input├── multiple .multiple(true) — chips + Backspace pops last└── emits ComboboxChangeEvent { value, selected }// Controlled selection — read it or drive it.combobox.update(cx, |c, cx| c.set_selected(&["Next.js"], cx));combobox.update_in(cx, |c, window, cx| { c.set_value(Some("Astro"), window, cx); // single select c.set_open(true, cx);});let current: Option<SharedString> = combobox.read(cx).selected_value();Keyboard
单行输入框不注册上下方向 handler —— 方向键以 input::MoveDown/MoveUp action 冒泡出来,组件在外层接住并驱动高亮行;Enter 走 input::Enter,Escape 走 input::Escape。多选下「空查询按 Backspace 删最后一个 chip」发生在绑定派发之前,由 keystroke interceptor 完成。
// Keyboard semantics ride GPUI's action system, not raw// key capture. A focused single-line input registers no// up/down handlers, so input::MoveUp / input::MoveDown// bubble out — the combobox listens for them and drives// the active row. Enter propagates as input::Enter,// Escape as input::Escape; both commit/close at the root.// One exception needs to run *before* bindings: Backspace// on an empty multi-select input is consumed by the editor,// so a keystroke interceptor pops the newest chip.Accessibility
Semantics
根元素带 role=combobox + aria-expanded;禁用项与禁用组件不响应指针与键盘;invalid 用红边 + 焦点环双重标识,不只靠颜色。
Keyboard
输入保持焦点:↓/↑ 移动高亮、Enter 提交、Escape 还原并关闭、Backspace 空查询时删 chip;列表超长时可滚动且高亮行自动滚入视野。
API Reference
实体暴露的 builder 方法、受控方法与事件。
| API | Signature | Notes |
|---|---|---|
Combobox::new(..) | Entity<InputState> | Wraps a caller-created input entity. |
.items(..) | Vec<ComboboxItem> | The collection; filtered as you type. |
ComboboxItem::new(..) | &str label | .value(..) .group(..) .hint(..) .disabled(..) |
.multiple(..) | bool | Chip selection; Enter/click toggles. |
.default_value(..) | &str | Initial single selection. |
.selected_values(..) | &[&str] | Initial multi selection. |
.clearable(..) | bool | ✕ button when a value is present. |
.empty_text(..) | &str | Shown when the query matches nothing. |
.invalid(..) | bool | Red border + focus ring. |
.disabled(..) | bool | Dimmed and inert. |
.set_value(..) | Option<&str>, Window, cx | Controlled single selection. |
.set_selected(..) | &[&str], cx | Controlled multi selection. |
.set_open(..) | bool, cx | Controlled popup open state. |
.selected_value() | -> Option<SharedString> | Current single selection. |
.selected_values_vec() | -> Vec<SharedString> | Current multi selection. |
ComboboxChangeEvent | { value, selected } | Emitted on every commit/toggle/clear. |
Source & inspiration
结构与交互参考 shadcn/ui Combobox (React Aria) 。本页交互由 Rust / GPUI 绘制,基础原语来自 gpui-kit 。