basecoat_core/props/select.rs
1use crate::{AttrMap, BasecoatProps, Children};
2use std::borrow::Cow;
3
4/// A single option in a [`SelectProps::options`] list.
5///
6/// Mirrors a native `<option>` element: `value` is the form-submitted value,
7/// `label` is the user-visible text, and `disabled` blocks selection.
8#[derive(Clone, Debug, Default)]
9pub struct SelectOption {
10 /// The form-submitted value for the `<option>`.
11 pub value: Cow<'static, str>,
12 /// The user-visible label shown in the trigger and listbox.
13 pub label: Cow<'static, str>,
14 /// Whether this option is disabled.
15 pub disabled: bool,
16}
17
18impl SelectOption {
19 /// Construct a new enabled option.
20 pub fn new(
21 value: impl Into<Cow<'static, str>>,
22 label: impl Into<Cow<'static, str>>,
23 ) -> Self {
24 Self {
25 value: value.into(),
26 label: label.into(),
27 disabled: false,
28 }
29 }
30
31 /// Mark this option as disabled.
32 pub fn disabled(mut self) -> Self {
33 self.disabled = true;
34 self
35 }
36}
37
38/// Select — maps to CSS class `.select` (custom-styled native form select).
39///
40/// Renders a hidden native `<select>` (the source of truth for form
41/// submission) alongside a visible trigger button and a floating listbox.
42/// The controller wires the listbox open/close behaviour, keyboard
43/// navigation, dismiss handling, and synchronizes the hidden element on
44/// option click.
45#[derive(BasecoatProps, Default, Clone, Debug)]
46pub struct SelectProps {
47 /// Unique DOM id for the trigger button — required for the controller
48 /// to find the element. The hidden `<select>` and listbox derive their
49 /// ids from this value.
50 #[prop(optional, into)]
51 pub id: Option<Cow<'static, str>>,
52 /// Form name for the hidden native `<select>` element.
53 #[prop(optional, into)]
54 pub name: Option<Cow<'static, str>>,
55 /// Accessible label associated via `aria-label` on the trigger.
56 #[prop(optional, into)]
57 pub label: Option<Cow<'static, str>>,
58 /// Initial selected value. Must match one of the option values.
59 #[prop(optional, into)]
60 pub value: Option<Cow<'static, str>>,
61 /// Placeholder text shown when no option is selected.
62 #[prop(optional, into)]
63 pub placeholder: Option<Cow<'static, str>>,
64 /// Whether the entire select is disabled.
65 #[prop(default = false)]
66 pub disabled: bool,
67 /// The list of selectable options.
68 #[prop(default)]
69 pub options: Vec<SelectOption>,
70 /// Extra CSS classes appended to the `.select` wrapper.
71 #[prop(optional, into)]
72 pub class: Option<Cow<'static, str>>,
73 /// Extra HTML attributes for the outer wrapper.
74 #[prop(extend)]
75 pub attrs: AttrMap,
76 /// Optional inline children (rendered inside the listbox before the
77 /// option buttons). Most callers should leave this empty and use
78 /// `options` instead.
79 pub children: Children,
80}