Select
Pick one value from a dropdown list.
1use herogpui::components::select::Select;Usage
Use the arrow keys and Enter or Space to select a language. Selection closes the list and keeps focus on the trigger. Values and options use 14px text with 20px lines. Section headers use 12px text with 16px lines and keep their own spacing. The popup flips near window edges and scrolls to keep options reachable in short windows.
1use herogpui::prelude::Select;
2
3Select::new("select-main", languages())
4 .label("Language")
5 .placeholder("Choose one")
6 .value(selected)
7 .is_open(is_open)
8 .on_open_change(bool_cb(cx.listener(|this, open: &bool, _, cx| {
9 this.select_open = *open;
10 cx.notify();
11 })))
12 .on_change(opt_usize_cb(cx.listener(
13 |this, i: &Option<usize>, _, cx| {
14 this.select_lang = *i;
15 this.select_open = false;
16 cx.notify();
17 },
18 )))Live HeroGPUI compiled to WebAssembly. Select any example without loading another WASM instance.
Anatomy
Rust types
Select
Select is assembled from these builders. The API reference lists each one.
Customization
Appearance builders and theme tokens Select uses.
Styling
| Style | Description |
|---|---|
Select text_size + line_height + section header styles | Text 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. |
conditional flex_col + gap(px(4.)) + default max_w(px(320.)) | The inner field wrapper stacks at four pixels only when label or description content exists; the root adds a 320px cap unless full width is enabled. |
description rendered only when !is_invalid | Description text is suppressed while the field is invalid. |
Label natural width | The shared label has natural content but does not explicitly opt out of flex-column stretching. |
h(px(36.)) + px(px(12.)) + field chrome | Primary trigger dimensions, chrome and typography. |
static trigger style | Pinned property transitions are immediate in GPUI. |
hover background | Hover field background. |
ring_if_focused + field focus background | Ring and background match; the focus background does not interpolate. |
invalid field border/ring + focus background | Invalid field treatment and focus background. |
disabled_opacity + listener suppression | Disabled opacity and interaction treatment. |
FieldVariant::Secondary | Lower-emphasis secondary trigger. |
flex_1 + text_size(px(14.)) + truncate | Alignment and size match, but GPUI truncates instead of wrapping long values. |
muted foreground | Placeholder colour. |
SelectionValue text/items only | Selected-value rendering does not include option checkmarks. |
chevron_down/chevron_up | GPUI uses a flow-positioned chevron and swaps glyphs without rotation animation. |
scrollable_field_popover + max_h_full (plain) / Infer (virtual) + floating_radius + overlay_shadow | Anchored to the measured trigger width 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 plain list scrolls the panel and the virtual list sizes itself to the same bound. Overlay surface, radius and shadow. |
Motion::LIST_IN + entering_zoom | Fade and zoom match; transform origin and placement slide are absent. |
Motion::LIST_OUT + exiting | Exit motion matches. |
panel p(px(6.)) + option px(px(10.)) | Six-pixel list inset and ten-pixel option-row horizontal padding. |
static indicator | GPUI has no indicator transition in either selection mode. |
root.w_full() + field.w_full() | Both the root and trigger expand to the available container width. |
API reference
Builders
| Builder | Type | Default | Description |
|---|---|---|---|
placeholder( | text | 'Select an item' | Temporary text shown while no option is selected. |
selection_mode( | SelectionMode | SelectionMode:: | Chooses single or multiple selection. |
is_open( | bool | — | Controlled popover open state. |
default_open( | bool | — | Initial uncontrolled popover state. |
on_open_change( | Fn( | — | Reports popover state changes. |
disabled_keys( | iterable of keys | — | Keys which cannot be selected or focused. |
is_disabled( | bool | — | Disables the field and its interactions. |
value( | Option< | — | Controlled selection; GPUI separates scalar and multiple values into typed builders. |
default_value( | Option< | — | Initial uncontrolled scalar or multiple selection, seeded once. |
on_change( | Fn( | — | Selection callback; scalar and multiple signatures use separate builders. |
is_required( | bool | — | Draws the required marker and makes an empty live FormField block native submission and focus the trigger. |
is_invalid( | bool | — | Forces the field into its invalid state. |
name( | string | — | Exports a live single- or multiple-selection FormField with disabled omission and reset behavior. |
full_width( | bool | false | Expands both the root and trigger to the available width. |
variant( | FieldVariant | FieldVariant:: | Selects the shadowed or lower-emphasis field chrome. |
new( | id, | — | Compound parts; GPUI takes a typed option collection and draws the field structure. |
value_content( | AnyElement | | — | Custom value content receives the live selected-value projection. |
indicator( | AnyElement | — | The similarly named GPUI builder replaces option checkmarks, not the trigger chevron. |
placement( | Placement | Placement:: | Eight 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. |
Parts
| Part | Description |
|---|---|
Select | Selection, form and overlay state owner. |
Select | Focus and press target; its internal content is not separately composable. |
Select | Placeholder or selected-value content with a live render projection. |
Select | Built-in trigger chevron; the public indicator closure belongs to list options instead. |
Select | List surface anchored to the trigger; it can flip within the window and supports a reduced placement vocabulary. |
States
| Builder | State | Description |
|---|---|---|
trigger hover style | Hovered trigger | Field background changes on pointer hover. |
ring_if_focused + focus-visible background | Focus visible | Keyboard focus rings the trigger and applies the field-focus background. Enter and Space finish a single selection without reopening a popup closed by its owner. |
is_disabled + live FormField is_successful | Disabled | Field is dimmed, inert, untabbable and omitted from FormData while disabled. |
is_invalid + description suppression | Invalid | Invalid field chrome applies the focus background and suppresses the description row. |
SelectionValue::is_placeholder | Placeholder | Empty value uses muted placeholder colour. |
is_open chevron selection | Open indicator | The glyph swaps direction immediately instead of rotating over 150ms. |
overlay_phase Entering + entering_zoom | Entering | 150ms Smooth fade and 95% zoom match; placement-specific four-pixel translation is absent. |
overlay_phase Exiting + exiting | Exiting | 100ms Smooth fade and zoom to 95%. |
selected option style + indicator | Selected option | Selection is visible, but GPUI adds accent text and weight beyond v3's indicator-only state. |
focused option border | Focused option | Keyboard focus is visible, but uses a two-pixel border rather than v3's status ring. |
disabled_keys | Disabled option | Disabled rows are dimmed and skipped by navigation and selection. |
SelectionMode::Multiple | Multiple selection | The popover stays open while multiple options are toggled. |