Pickers

Autocomplete

An autocomplete combines a select with filtering, allowing users to search and select from a list of options.

Rust
1use herogpui::components::autocomplete::Autocomplete;

Usage

Values and options use 14px text with 20px lines. Section headers use 12px text with 16px lines and keep their own spacing. The popup anchors to the trigger with an 8px gap, flips when the preferred side cannot fit and the opposite side has more room, keeps the search visible, and scrolls the list within the available height up to 320px; virtual paging follows the visible list height.

Rust
1use herogpui::prelude::Autocomplete;
2
3Autocomplete::new(
4    self.ac_entity.clone(),
5    language_items(),
6)
7.label("Language")
8.placeholder("Select a language")

Live HeroGPUI compiled to WebAssembly. Select any example without loading another WASM instance.

Anatomy

Rust types

Autocomplete

Autocomplete is assembled from these builders. The API reference lists each one.

Customization

Appearance builders and theme tokens Autocomplete uses.

Styling

Autocomplete styling
StyleDescription
Autocomplete text_size + line_height + section header stylesText keeps its line height under surrounding styles. Section headers have 8px horizontal, 6px top and 4px bottom padding; selecting an option does not add font weight.
flex_col + gap(px(4.))Four-pixel field stack with label and message siblings.
FIELD_HEIGHT + apply_field_chrome + px(px(12.))Matches the field tokens but adds a 180px local floor when fullWidth is false.
apply_field_chrome + field.hoverStatic hover, focus and invalid colors match, but those trigger-color changes still swap in one frame.
FieldVariant::Secondary + apply_field_chromeSecondary field chrome uses the lower-emphasis default palette.
flex_1 + truncate + FIELD_TEXT + field colorsTypography and colors match, while truncates long selected text instead of wrapping it.
absolute right(px(8.)) + FIELD_ICON + indicator(render)Position and size match; the built-in glyph swaps direction and custom content receives open state, but no rotation interpolation is applied.
size(px(20.)) + p(px(4.)) + small_radius + hoverSize, radius, padding and hover match; pressed scale and the 150ms visible opacity transition are not reproduced.
placement(Placement) + pt(px(8.)) + max_h(px(320.)) + scroll + overlay bg/shadowAnchors to the measured trigger with an 8px gap, flipping to the side with more room when the preferred side cannot fit and keeping a 12px cross-axis viewport inset with the scroller capped to the available height; the search stays visible while the inner list scrolls and shrinks to the available height within the upstream 320px max, and virtual paging follows the visible list height. The reduced placement vocabulary and placement slide remain unported.
entering_zoom + Motion::FLUID_INFade, zoom, duration and curve match; placement-specific one-step translation is not reproduced.
exiting + Motion::FLUID_OUTExit fade, geometry, duration and curve match through retained overlay frames.
SearchField::new + px(px(12.)) + py(px(4.))The built-in secondary SearchField uses the documented 12px/4px wrapper inset and stays visible while the inner list scrolls.
max_h/h(px(320.)) + p(px(6.)) + scrollBoth normal and virtual lists use the upstream 320px cap with a six-pixel inset; the list shrinks below the cap to the available height and virtual paging follows the visible list height.
row px(px(10.)) + FIELD_HEIGHT + soft_radiusRows use the documented ten-pixel horizontal inset and the shared ListBox item geometry.
full_width(true) + w_fullFull-width root and trigger.

API reference

Builders

Autocomplete builders
BuilderTypeDefaultDescription
placeholder(value)string'Select an item'Temporary trigger text while no item is selected.
selection_mode(SelectionMode)SelectionModeSelectionMode::SingleWhether one or multiple options may be selected.
allows_empty_collection(bool)boolfalseAllows the trigger to open when the unfiltered collection has no items.
is_open(bool)boolControlled popover open state.
default_open(bool)boolfalseInitial popover state for an uncontrolled Autocomplete.
on_open_change(callback)Fn(isOpen: bool) -> ()Reports trigger, keyboard, selection, blur, Escape and outside-press open changes.
disabled_keys(keys)iterable of keysKeys of the options that remain visible but cannot be selected; per key, so one of two same-label items can be disabled alone.
is_disabled(bool)boolfalseRemoves the trigger from interaction and form submission and prevents the popover from opening.
value(keys)Key | Key[] | nullControlled selection as an iterable of item keys; the trigger renders each selected key's label once in selection insertion order.
default_value(keys)Key | Key[] | nullUncontrolled selection seed as an iterable of item keys; the held selection survives filtering and reordering by key.
on_selection_change_all(callback)Fn(value: Key | Key[] | null) -> ()Reports the complete selection as an empty, single-key or multiple-key slice.
is_required(bool)boolfalseMarks an empty successful field invalid for native Form submission and labels it required.
is_invalid(bool)boolfalseMarks the field invalid, applies invalid chrome and exposes invalid Form state.
name(value)stringNames the live FormField returned by form_field().
full_width(bool)boolfalseFills the available horizontal space.
variant(FieldVariant)FieldVariantFieldVariant::PrimarySelects the elevated or lower-emphasis field chrome.
new(state, items)state, itemsBuilds the documented compound anatomy monolithically from state and items.
value_content(render)AnyElement | render closureCustom value content receives the local SelectionValue projection.
indicator(render)AnyElementAnyElement::DefaultChevronReplaces the trigger chevron; the local closure also receives the open state.
on_clear(callback)Fn(event: MouseEvent) -> ()The local callback runs after selection clears but does not receive a browser MouseEvent; the button renders and clears without it.
placement(Placement)PlacementPlacement::BottomEight cardinal/start/end placements are available; RAC's full 22-value placement union is not. The panel anchors to the measured trigger with an 8px gap and flips when the preferred side cannot fit and the opposite side has more room.
filter(callback)Fn(text: string, input: string) -> booluseFilter containsReplaces the built-in matcher with a caller-supplied predicate.
input_value(value)stringControls the visible search text and filtering value.
on_input_change(callback)Fn(value: string) -> ()Reports proposed search edits while a controlled value remains owner-owned.

Parts

Autocomplete parts
PartDescription
AutocompleteRoot field stack owning selection, open state, filtering, form state and the floating panel.
AutocompleteField-shaped trigger with value, clear button and indicator; it is built in rather than independently composable.
AutocompleteSelected labels or placeholder, with a SelectionValue render closure.
AutocompleteDefault chevron or caller content receiving the current open state.
AutocompleteBuilt-in clear affordance always mounted with the trigger; invisible and pointer-inert while the selection is empty, inert when disabled, and left working by read-only.
AutocompletePlacement-aware overlay with pinned entry/exit motion, outside dismissal, SearchField and ListBox content.
AutocompleteSearch value and matcher boundary applied to the collection inside the popover.

States

Autocomplete states
BuilderStateDescription
open + indicator(render)OpenThe trigger indicator receives the live open state and the popover is mounted.
field.hover(background)HoveredEnabled trigger hover changes its field background while the clear button inside is not itself hovered; the color change is not interpolated.
ring_if_focused(field, handle, true, ...)Focus visibleKeyboard-visible trigger focus draws the offset status ring.
is_disabled + interaction/form gatesDisabledThe trigger leaves the tab order, cannot open and is omitted from FormData.
is_read_only + interaction gatesRead onlyThe selection remains visible while opening and query edits are inert; gates the clear button on disabled only, so it keeps working.
is_invalid/error_message + form_stateInvalidInvalid chrome and error content replace the normal description and block native Form submission.
is_required + form_fieldRequiredThe label and FormField carry required state; an empty value blocks native submission.
is_placeholder + value_contentPlaceholderMissing selected items use the placeholder palette and value render state.
clear_empty + clear_active gatesEmpty selectionThe always-mounted clear affordance turns invisible and pointer-inert (opacity-0 with hit testing-none) while the selection is empty.
selection_mode(Multiple) + on_selection_change_allMultiple selectionRows toggle membership, keep the panel open and report the whole selection.
toggle_allowed + allows_empty_collectionEmpty collectionAn empty unfiltered collection can open only when explicitly allowed.
entering_zoom + Motion::FLUID_INEnteringThe panel fades and grows from 95% over 250ms with ease-out-fluid; placement slide is not reproduced.
overlay_phase + exiting + Motion::FLUID_OUTExitingThe retained panel fades and shrinks to 95% over 100ms with ease-out-quad.