Dropdown
A menu that opens on click and closes on selection or an outside click. The
outside-click handler is the sanctioned document-level listener: added in
onCreate, removed in onDestroy.
Markup
<button @click="toggle" data-bind="aria-expanded:open ? 'true' : 'false'" aria-haspopup="menu">
Options <span>v</span>
</button>
<div role="menu" data-show="open">
<template data-each="items" data-key="id">
<button role="menuitem" @click="choose" data-bind="data-label:item.label" data-text="item.label"></button>
</template>
</div>
<p>Selected: <span data-text="selected || 'none'"></span></p>
Component
Micra.define("dropdown", {
state: {
open: false,
selected: "",
items: [
{ id: 1, label: "Rename" },
{ id: 2, label: "Duplicate" },
{ id: 3, label: "Archive" },
{ id: 4, label: "Delete" },
],
},
toggle() {
this.state.open = !this.state.open;
},
choose(e) {
this.state.selected = e.currentTarget.dataset.label;
this.state.open = false;
},
onCreate() {
this._outside = (e) => {
if (!this.$el.contains(e.target)) this.state.open = false;
};
document.addEventListener("click", this._outside);
},
onDestroy() {
document.removeEventListener("click", this._outside);
},
});
this.$el is the component root, so contains cleanly distinguishes clicks
inside the menu from clicks anywhere else on the page.