Dropdown Menu

Click-toggle menu that closes on outside click or Escape key.

Live Demo

Source

HTML + JavaScript
<div data-component="my-dropdown">
    <!-- data-event-outside goes on the WRAPPER. The toggle button is
         inside it, so opening the menu is not treated as an outside
         click and the menu stays open. -->
    <div class="dropdown-wrapper" data-event-outside
         data-action="click:closeMenu">
        <button data-action="toggleMenu">Actions &#9662;</button>

        <div class="dropdown-menu" data-show="menuOpen">
            <div data-list="menuItems">
                <template>
                    <div class="dropdown-item" data-bind="label"
                         data-action="pickItem"></div>
                </template>
            </div>
        </div>
    </div>
    <span data-bind="lastAction"></span>
</div>

<script>
wildflower.component('my-dropdown', {
    state: {
        menuOpen: false,
        lastAction: '',
        menuItems: [
            { label: 'Edit', action: 'edit' },
            { label: 'Duplicate', action: 'duplicate' },
            { label: 'Archive', action: 'archive' },
            { label: 'Delete', action: 'delete' }
        ]
    },
    toggleMenu() { this.menuOpen = !this.menuOpen; },
    closeMenu() { this.menuOpen = false; },
    pickItem(e, el, { index }) {
        this.lastAction = 'Picked: ' + this.menuItems[index].label;
        this.menuOpen = false;
    }
});
</script>

Key Points

  • data-event-outside goes on the wrapper, not the menu, so the action fires only on clicks outside the whole dropdown
  • Because the toggle button is inside that wrapper, opening the menu is not counted as an outside click, so it does not instantly close
  • data-show="menuOpen" on the menu element handles visibility; data-cloak prevents a flash before binding
  • Menu items rendered from an array with data-list; pickItem and closeMenu both set menuOpen to false