BasecoatUI components for htmy.

Dropdown Menu

Example:


Code example:

from htmy import ComponentType, html

from htmui.basecoat.dropdown_menu import dropdown_menu
from htmui.basecoat.menu import menu_item, menu_item_group
from htmui.basecoat.separator import separator


def example() -> ComponentType:
    return dropdown_menu(
        menu_item_group(
            menu_item(html.span("Commit"), shortcut="⌘+K"),
            menu_item(html.span("Pull"), shortcut="⇧⌘P"),
            menu_item(html.span("Push"), shortcut="⇧⌘K"),
            id="dropdown-group-1",
            label="Git",
            label_props={"class": "font-semibold"},
        ),
        separator,
        menu_item_group(
            menu_item(html.span("Approve"), kind="radio", checked=True, shortcut="⌘+A"),
            menu_item(html.span("Comment"), kind="radio", disabled=True, shortcut="⌘+/"),
            menu_item(html.span("Reject"), kind="radio", shortcut="⌘+R"),
            id="dropdown-group-2",
            label="Review",
            label_props={"class": "font-semibold"},
        ),
        button_content="Dropdown menu",
        id="dropdown-example",
    )

Component implementation:

For more details, see the BasecoatUI documentation.

from htmy import ComponentType, PropertyValue, SafeStr, html, join_classes

from .button import ButtonVariant
from .typing import Align, FloatingSide

__version__ = "0.2.0"
__framework__ = "BasecoatUI"
__framework_version__ = "1"
__framework_url__ = "https://basecoatui.com/components/dropdown-menu/"


js = SafeStr(
    '<script src="https://cdn.jsdelivr.net/npm/basecoat-css@1/dist/js/dropdown-menu.min.js" defer></script>'
)


def dropdown_menu(
    *items: ComponentType,
    id: str,
    button_content: ComponentType,
    button_class: str | None = None,
    button_variant: ButtonVariant | None = "outline",
    class_: str | None = None,
    popover_class: str | None = None,
    popover_align: Align | None = None,
    popover_side: FloatingSide | None = None,
    **kwargs: PropertyValue,
) -> ComponentType:
    menu_id = f"{id}-menu"
    button_id = f"{menu_id}-button"

    return html.div(
        html.button(
            button_content,
            type="button",
            id=button_id,
            aria_controls=menu_id,
            aria_expanded="false",
            aria_haspopup="menu",
            class_=join_classes("btn", button_class),
            **({"data_variant": button_variant} if button_variant else {}),
        ),
        html.div(
            html.div(
                *items,
                id=menu_id,
                role="menu",
                aria_labelledby=button_id,
            ),
            data_popover="",
            aria_hidden="true",
            class_="min-w-56" if popover_class is None else popover_class,
            data_align=popover_align,
            data_side=popover_side,
        ),
        class_=join_classes("dropdown-menu", class_),
        id=id,
        **kwargs,
    )