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}