Combo box, searchable dropdown with free-form text input.
The renderer manages an internal combo_box::State cache keyed by node ID.
Options changes trigger a state rebuild.
Props
| Name | Type | Default | Description |
|---|---|---|---|
options | [String.t() | atom()] | required | Available choices. |
selected | String.t() | atom() | nil | Currently selected value. Also accepts :value as alias. |
placeholder | String.t() | atom() | nil | Placeholder text. |
width | :fill | :shrink | {:fill_portion, pos_integer()} | number() | nil | Widget width. Default: fill. |
padding | number() | {number(), number()} | %Plushie.Type.Padding{} | nil | Internal padding. |
size | number() | nil | Text size in pixels. |
font | :default | :monospace | String.t() | %Plushie.Type.Font{} | nil | Font specification. |
line_height | number() | %{relative: number()} | %{absolute: number()} | nil | Text line height. |
menu_height | number() | nil | Maximum dropdown menu height in pixels. |
icon | map() | nil | Icon inside the text input. |
on_option_hovered | boolean() | nil | Emit hover events over dropdown options. |
on_open | boolean() | nil | Emit open event when the dropdown opens. |
on_close | boolean() | nil | Emit close event when the dropdown closes. |
shaping | :basic | :advanced | :auto | nil | Text shaping strategy. |
ellipsis | :none | :start | :middle | :end | nil | Text ellipsis: :none, :start, :middle, or :end. |
menu_style | map() | nil | Inline style for the dropdown menu. |
| style | :default \| :primary \| :secondary \| :success \| :danger \| :warning \| :dark \| :weak \| :rounded_box \| term() | nil | Named preset or custom StyleMap. |
| required | boolean() | nil | Marks the field as required. Flows into a11y.required automatically. |
| validation | term() | nil | Form validation state. Accepts :valid, :pending, or {:invalid, message}. Flows into a11y.invalid and a11y.error_message automatically. |
| event_rate | integer() | nil | Max events per second for coalescable events. |
| a11y | %Plushie.Type.A11y{} \| map() \| keyword() | %{role: :combo_box, label_from: :placeholder, has_popup: "listbox"} | Accessibility annotations. |
Events
| Event | Type | Description |
|---|---|---|
:select | value: String.t() | atom() | Emitted when an option is selected. |
:input | value: String.t() | atom() | Emitted on every text input change (for filtering). |
:option_hovered | value: String.t() | atom() | Emitted on hover (requires on_option_hovered). |
:open | none | Emitted when dropdown opens (requires on_open: true). |
:close | none | Emitted when dropdown closes (requires on_close: true). |
Constructor
ComboBox.new(id, options)
ComboBox.new(id, options, opts)
Summary
Functions
Accessibility annotations.
Converts this widget struct to a ui_node() map.
Creates a :combo_box widget.
Text ellipsis: :none, :start, :middle, or :end.
Max events per second for coalescable events.
Font specification.
Icon inside the text input.
Text line height.
Maximum dropdown menu height in pixels.
Inline style for the dropdown menu.
Creates a new widget struct with the given positional args and keyword options.
Emit close event when the dropdown closes.
Emit open event when the dropdown opens.
Emit hover events over dropdown options.
Available choices.
Internal padding.
Placeholder text.
Marks the field as required. Flows into a11y.required automatically.
Currently selected value. Also accepts :value as alias.
Text shaping strategy.
Text size in pixels.
Named preset or custom StyleMap.
Form validation state. Accepts :valid, :pending, or {:invalid, message}. Flows into a11y.invalid and a11y.error_message automatically.
Widget width. Default: fill.
Applies keyword options to an existing widget struct.
Types
@type option() :: (((((((((((((((((({:selected, String.t() | atom()} | {:placeholder, String.t() | atom()}) | {:width, :fill | :shrink | {:fill_portion, pos_integer()} | number()}) | {:padding, number() | {number(), number()} | %Plushie.Type.Padding{ bottom: term(), left: term(), right: term(), top: term() }}) | {:size, number()}) | {:font, :default | :monospace | String.t() | %Plushie.Type.Font{ family: term(), stretch: term(), style: term(), weight: term() }}) | {:line_height, number() | %{relative: number()} | %{absolute: number()}}) | {:menu_height, number()}) | {:icon, map()}) | {:on_option_hovered, boolean()}) | {:on_open, boolean()}) | {:on_close, boolean()}) | {:shaping, :basic | :advanced | :auto}) | {:ellipsis, :none | :start | :middle | :end}) | {:menu_style, map()}) | {:style, :default | :primary | :secondary | :success | :danger | :warning | :dark | :weak | :rounded_box | term()}) | {:required, boolean()}) | {:validation, term()}) | {:event_rate, integer()}) | {:a11y, %Plushie.Type.A11y{ active_descendant: term(), busy: term(), described_by: term(), description: term(), disabled: term(), error_message: term(), expanded: term(), has_popup: term(), hidden: term(), invalid: term(), label: term(), label_from: term(), labelled_by: term(), level: term(), live: term(), mnemonic: term(), modal: term(), orientation: term(), position_in_set: term(), radio_group: term(), read_only: term(), required: term(), role: term(), selected: term(), size_of_set: term(), toggled: term(), value: term() } | map() | keyword()}
@type t() :: %Plushie.Widget.ComboBox{ a11y: (%Plushie.Type.A11y{ active_descendant: term(), busy: term(), described_by: term(), description: term(), disabled: term(), error_message: term(), expanded: term(), has_popup: term(), hidden: term(), invalid: term(), label: term(), label_from: term(), labelled_by: term(), level: term(), live: term(), mnemonic: term(), modal: term(), orientation: term(), position_in_set: term(), radio_group: term(), read_only: term(), required: term(), role: term(), selected: term(), size_of_set: term(), toggled: term(), value: term() } | map() | keyword()) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, ellipsis: (:none | :start | :middle | :end) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, event_rate: integer() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, font: (:default | :monospace | String.t() | %Plushie.Type.Font{ family: term(), stretch: term(), style: term(), weight: term() }) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, icon: map() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, id: String.t(), line_height: (number() | %{relative: number()} | %{absolute: number()}) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, menu_height: number() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, menu_style: map() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, on_close: boolean() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, on_open: boolean() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, on_option_hovered: boolean() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, options: [String.t() | atom()] | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, padding: (number() | {number(), number()} | %Plushie.Type.Padding{ bottom: term(), left: term(), right: term(), top: term() }) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, placeholder: (String.t() | atom()) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, required: boolean() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, selected: (String.t() | atom()) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, shaping: (:basic | :advanced | :auto) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, size: number() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, style: (:default | :primary | :secondary | :success | :danger | :warning | :dark | :weak | :rounded_box | term()) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, validation: term() | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil, width: (:fill | :shrink | {:fill_portion, pos_integer()} | number()) | Plushie.Animation.Transition.t() | Plushie.Animation.Spring.t() | Plushie.Animation.Sequence.t() | nil }
Functions
@spec a11y( widget :: t(), value :: (%Plushie.Type.A11y{ active_descendant: term(), busy: term(), described_by: term(), description: term(), disabled: term(), error_message: term(), expanded: term(), has_popup: term(), hidden: term(), invalid: term(), label: term(), label_from: term(), labelled_by: term(), level: term(), live: term(), mnemonic: term(), modal: term(), orientation: term(), position_in_set: term(), radio_group: term(), read_only: term(), required: term(), role: term(), selected: term(), size_of_set: term(), toggled: term(), value: term() } | map() | keyword()) | nil ) :: t()
Accessibility annotations.
Accepts %Plushie.Type.A11y{} | map() | keyword().
@spec build(widget :: t()) :: Plushie.Widget.ui_node()
Converts this widget struct to a ui_node() map.
Creates a :combo_box widget.
Shorthand for new/2. Import this macro to use the widget name
directly in view functions:
import Plushie.Widget.ComboBox, only: [combo_box: 2]
combo_box("my-id", prop: value)
Text ellipsis: :none, :start, :middle, or :end.
Accepts :none | :start | :middle | :end.
Max events per second for coalescable events.
Accepts integer().
@spec font( widget :: t(), value :: (:default | :monospace | String.t() | %Plushie.Type.Font{ family: term(), stretch: term(), style: term(), weight: term() }) | nil ) :: t()
Font specification.
Accepts :default | :monospace | String.t() | %Plushie.Type.Font{}.
Icon inside the text input.
Accepts map().
@spec line_height( widget :: t(), value :: (number() | %{relative: number()} | %{absolute: number()}) | nil ) :: t()
Text line height.
Accepts number() | %{relative: number()} | %{absolute: number()}.
Creates a new widget struct with the given positional args and keyword options.
Arguments
id- unique widget identifieroptions- Available choices.opts- keyword list of optional props
Emit close event when the dropdown closes.
Accepts boolean().
Emit open event when the dropdown opens.
Accepts boolean().
Emit hover events over dropdown options.
Accepts boolean().
Available choices.
Accepts [String.t() | atom()].
@spec padding( widget :: t(), value :: (number() | {number(), number()} | %Plushie.Type.Padding{ bottom: term(), left: term(), right: term(), top: term() }) | nil ) :: t()
Internal padding.
Accepts number() | {number(), number()} | %Plushie.Type.Padding{}.
Placeholder text.
Accepts String.t() | atom().
Marks the field as required. Flows into a11y.required automatically.
Accepts boolean().
Currently selected value. Also accepts :value as alias.
Accepts String.t() | atom().
Text shaping strategy.
Accepts :basic | :advanced | :auto.
Text size in pixels.
Accepts number().
@spec style( widget :: t(), value :: (:default | :primary | :secondary | :success | :danger | :warning | :dark | :weak | :rounded_box | term()) | nil ) :: t()
Named preset or custom StyleMap.
Accepts :default | :primary | :secondary | :success | :danger | :warning | :dark | :weak | :rounded_box | term().
Form validation state. Accepts :valid, :pending, or {:invalid, message}. Flows into a11y.invalid and a11y.error_message automatically.
Accepts term().
@spec width( widget :: t(), value :: (:fill | :shrink | {:fill_portion, pos_integer()} | number()) | nil ) :: t()
Widget width. Default: fill.
Accepts :fill | :shrink | {:fill_portion, pos_integer()} | number().
Applies keyword options to an existing widget struct.