Skip to main content

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}