Skip to main content

basecoat_core/props/
combobox.rs

1use crate::{AttrMap, BasecoatProps, Children};
2use std::borrow::Cow;
3
4/// A single option in a Combobox listbox.
5#[derive(Clone, Debug, Default)]
6pub struct ComboboxOption {
7    /// Submitted form value for the option.
8    pub value: Cow<'static, str>,
9    /// User-visible label rendered inside the option.
10    pub label: Cow<'static, str>,
11}
12
13impl ComboboxOption {
14    pub fn new(
15        value: impl Into<Cow<'static, str>>,
16        label: impl Into<Cow<'static, str>>,
17    ) -> Self {
18        Self {
19            value: value.into(),
20            label: label.into(),
21        }
22    }
23}
24
25/// Combobox — input with a filtered listbox of suggestions.
26///
27/// Reuses the upstream `.select` CSS class for the wrapper because Basecoat
28/// styles `input[role=combobox]` through the `.select` layer.
29///
30/// The DOM contract emitted by the matching component function is:
31///
32/// ```html
33/// <div class="select" id="{id}" data-combobox
34///      data-basecoat-hydrate="combobox"
35///      data-basecoat-version="0.2">
36///   <input type="text" role="combobox"
37///          aria-controls="{id}-listbox"
38///          aria-expanded="false"
39///          aria-autocomplete="list"
40///          autocomplete="off"
41///          data-combobox-input>
42///   <div role="listbox" id="{id}-listbox" data-combobox-listbox hidden>
43///     <button type="button" role="option"
44///             id="{id}-option-{idx}"
45///             data-value="{value}"
46///             tabindex="-1">{label}</button>
47///     ...
48///   </div>
49/// </div>
50/// ```
51#[derive(BasecoatProps, Default, Clone, Debug)]
52pub struct ComboboxProps {
53    /// Unique DOM id — required for the WASM controller to wire ARIA and the
54    /// listbox association.
55    #[prop(optional, into)]
56    pub id: Option<Cow<'static, str>>,
57    /// Form field name for the hidden value.
58    #[prop(optional, into)]
59    pub name: Option<Cow<'static, str>>,
60    /// Placeholder text rendered in the empty input.
61    #[prop(optional, into)]
62    pub placeholder: Option<Cow<'static, str>>,
63    /// Initial input value (rendered as `value="..."`).
64    #[prop(optional, into)]
65    pub value: Option<Cow<'static, str>>,
66    /// Static set of options. Dynamic loading is planned for a future release.
67    #[prop(default)]
68    pub options: Vec<ComboboxOption>,
69    /// Disable the input element.
70    #[prop(default)]
71    pub disabled: bool,
72    /// Extra CSS classes appended to the canonical `.select` class.
73    #[prop(optional, into)]
74    pub class: Option<Cow<'static, str>>,
75    #[prop(extend)]
76    pub attrs: AttrMap,
77    /// Slot reserved for downstream extensions; the bundled component
78    /// function ignores `children` and renders options from `options`.
79    pub children: Children,
80}