basecoat_core/props/dropdown.rs
1use crate::{AttrMap, BasecoatProps, Children, Markup};
2use std::borrow::Cow;
3
4/// A single item in a dropdown menu.
5///
6/// Items render as `<button type="button" role="menuitem" tabindex="-1">`
7/// inside the floating menu container.
8#[derive(Clone, Debug, Default)]
9pub struct DropdownItem {
10 /// Visible text label.
11 pub label: Cow<'static, str>,
12 /// Optional unique value attached to the item (rendered as
13 /// `data-value="..."`). Useful when the host application needs to map
14 /// item activation back to a domain-level identifier.
15 pub value: Option<Cow<'static, str>>,
16 /// When true, the rendered button carries `disabled` and
17 /// `aria-disabled="true"`.
18 pub disabled: bool,
19}
20
21impl DropdownItem {
22 /// Convenience constructor for a simple label-only item.
23 pub fn new(label: impl Into<Cow<'static, str>>) -> Self {
24 Self {
25 label: label.into(),
26 value: None,
27 disabled: false,
28 }
29 }
30}
31
32/// Dropdown — maps to CSS class `.dropdown-menu`.
33///
34/// The DOM contract is:
35///
36/// ```html
37/// <details class="dropdown-menu" data-basecoat-hydrate="dropdown"
38/// data-basecoat-version="0.2" data-dropdown id="{id}">
39/// <summary aria-haspopup="menu" aria-expanded="false">{trigger}</summary>
40/// <div role="menu">
41/// <button type="button" role="menuitem" tabindex="-1">{label}</button>
42/// ...
43/// </div>
44/// </details>
45/// ```
46///
47/// `id` is required so the WASM controller can attach.
48#[derive(BasecoatProps, Default, Clone, Debug)]
49pub struct DropdownProps {
50 /// Unique DOM id — required for the WASM controller.
51 #[prop(optional, into)]
52 pub id: Option<Cow<'static, str>>,
53 /// Trigger content (rendered inside `<summary>`).
54 #[prop(optional)]
55 pub trigger: Option<Markup>,
56 /// Items rendered inside the menu container.
57 #[prop(default)]
58 pub items: Vec<DropdownItem>,
59 /// Optional aria-label for the menu container.
60 #[prop(optional, into)]
61 pub menu_label: Option<Cow<'static, str>>,
62 /// Floating placement string passed to `@floating-ui/dom`
63 /// (default `"bottom-start"`).
64 #[prop(optional, into)]
65 pub placement: Option<Cow<'static, str>>,
66 /// Extra CSS classes appended after `dropdown-menu`.
67 #[prop(optional, into)]
68 pub class: Option<Cow<'static, str>>,
69 #[prop(extend)]
70 pub attrs: AttrMap,
71 pub children: Children,
72}