Skip to content
Glint UI

DropdownMenu

A click-triggered menu with keyboard navigation, grouped items, checkable options, and nested submenus.

Usage

import { Button } from "@glint/components/button.slint";
import { DropdownMenu } from "@glint/components/dropdown-menu.slint";
export component AppWindow inherits Window {
VerticalLayout {
alignment: center;
menu := DropdownMenu {
items: [
{ label: "Profile" },
{ label: "Billing" },
{ label: "Sign out", separator-before: true }
];
selected(row, child) => {
// handle choice
}
Button {
text: "My Account";
haspopup: true;
clicked => { menu.show(); }
}
}
}
}

DropdownMenu wraps a trigger element in its @children slot (typically a Button). Clicking the trigger opens a popup card powered by MenuPanel presenting the items model. The menu manages keyboard navigation, submenus, checkable items, and radio groups.

The model is two-way: activating a checkbox or radio row immediately updates the checked property in the items array before the selected(row, child) callback fires.

Examples

When a menu row carries children, hovering it or pressing opens a submenu panel. Use submenu-side (PanelSide.right, PanelSide.left) and submenu-align (PanelAlign.start, PanelAlign.center, PanelAlign.end) to control where the nested panel appears relative to the parent item.

Checkable and radio rows

Set checkable: true on an item for a toggleable checkbox row. Adding a non-empty radio-group string links the item into a mutually exclusive group where picking one item clears other items in the same group on the same frame.

Group headings and destructive items

Following the grouped rows model, use separator-before: true and heading-before: "..." to group related options without changing item indexing. Set tone: MenuTone.destructive on actions that delete or destroy data.

API Reference

Properties

PropertyTypeDefaultDescription
itemsin-out [MenuEntry]no defaultMenu rows shown when the trigger is clicked. in-out because activating a checkbox or radio row writes its new checked back here.
min-content-widthin length200pxThe floor under the popup panel's width; the panel grows past it to fit its widest row, icon and shortcut hint included.
submenu-sidein PanelSidePanelSide.rightWhere a row's submenu panel opens: which side of the menu, and how it lines up against the row it hangs off. A submenu opens beside its row, so top and bottom read as right.
submenu-alignin PanelAlignPanelAlign.start
highlighted-indexin-out int0Row highlighted by ↑/↓ inside the open popup; consumers rarely set this.
is-openout boolno defaultTrue while the menu is on screen; mirrors PopupWindow.is-open.

Callbacks

CallbackDescription
selected(int , int)Fired with the chosen row's index, and with the index of the submenu leaf that was taken or -1 when the row itself was; the popup auto-closes.

Functions

FunctionDescription
show()Opens the menu with the highlight back at the top. Mirrors PopupWindow.show() — wire it to a consumer-owned trigger so the menu opens from the keyboard as well as from a click.
close()Closes the menu. Mirrors PopupWindow.close().

Enums

EnumValues
PanelSidetop, right, bottom, left
PanelAlignstart, center, end

Accessibility

  • Role and structure. The open dropdown menu presents an accessible list containing list-item rows with accessible-item-count and 1-based accessible-item-index values.
  • Checkable and expandable states. Checkbox and radio rows announce their checked state, and rows with submenus announce themselves as expandable.
  • Shortcut hints. Shortcut strings ride as accessible-description on the row rather than creating extra text nodes.
  • Group headings. Group headers and separator lines are presented as non-actionable labels and never receive keyboard focus.
  • Keyboard navigation. / navigate the list, Home/End jump to the first and last options, opens a submenu, closes the active submenu, Enter or Space activates the highlighted option, and Escape closes the menu (or the open submenu first).