Skip to content

Menu API Reference ​

Props ​

PropTypeDefaultDescription
triggerTypeString'click'How the menu opens. Accepts 'click' or 'hover'.
offsetArray[0, 0.125][x, y] offset, expressed in REM units, applied to the computed position.
placementString'bottom'Preferred placement relative to the trigger (see list below).
closeOnOutsideClickBooleantrueClose when the user clicks outside the trigger/menu.
closeOnEscBooleantrueClose when the Escape key is pressed.
widthString/NumbernullExplicit menu width (CSS string or number in pixels).
matchTriggerWidthBooleantrueSync the menu width with the trigger when width is not provided.
menuContentClassArray[]Additional class names applied to the floating menu element.
disabledBooleanfalsePrevents the trigger from toggling the menu.
fixedXString''Override the computed left position (any CSS length/percentage).
fixedYString''Override the computed top position (any CSS length/percentage).
menuIdString''Adds deterministic IDs ({menuId}Trigger / {menuId}Content) for accessibility.
stopPropagationBooleantrueStops trigger click propagation; set false to allow parent listeners.

Placement Options ​

OMenu accepts: top, bottom, left, right, top-start, top-end, bottom-start, bottom-end, left-top, left-bottom, right-top, right-bottom. Collision detection can flip your preferred placement automatically to keep the menu inside the viewport.

Events ​

EventPayloadDescription
open-Fired after the menu opens.
close-Fired after the menu closes.

Slots ​

SlotDescription
triggerThe interactive element that toggles the menu. Receives { isOpen }.
contentThe floating menu content.

Exposed Methods ​

MethodDescription
openMenu()Programmatically open the menu.
closeMenu()Programmatically close the menu.
toggleMenu()Toggle the open/closed state.

Exposed Properties ​

PropertyTypeDescription
isOpenBooleanCurrent open state of the menu.
actualPlacementStringFinal placement after collision adjustments.

Features ​

Collision Detection ​

Viewport-aware logic flips or nudges the menu when the requested placement would overflow the visible window.

Hover Support ​

Set triggerType="hover" to open on mouse enter and close shortly after mouse leave, preventing accidental dismissals.

Responsive Positioning ​

The menu recalculates its position on window resize and scroll events to stay aligned with the trigger (unless fixedX/fixedY are provided).

Teleport ​

Menu content teleports to document.body to avoid stacking-context issues. Use menuContentClass to attach additional styling to the teleported element.

Example Usage ​

vue
<template>
  <OMenu
    ref="menuRef"
    trigger-type="click"
    placement="bottom-start"
    :width="280"
    :match-trigger-width="false"
    :menu-content-class="['elevation-panel']"
    @open="handleOpen"
    @close="handleClose"
  >
    <template #trigger>
      <button class="menu-trigger">
        Actions
        <span aria-hidden="true">▾</span>
      </button>
    </template>

    <template #content>
      <div class="menu-items">
        <button class="menu-item">Edit</button>
        <button class="menu-item">Duplicate</button>
        <button class="menu-item" disabled>Archive (disabled)</button>
      </div>
    </template>
  </OMenu>

  <button @click="menuRef?.openMenu()">Open programmatically</button>
  <button @click="menuRef?.closeMenu()">Close programmatically</button>
</template>

<script setup>
import { ref } from 'vue';

const menuRef = ref(null);

const handleOpen = () => {
  console.log('Menu opened');
};

const handleClose = () => {
  console.log('Menu closed');
};
</script>

Menu API Reference ​

Props ​

PropTypeDefaultDescription
triggerTypeString'click'How to open the menu. Options: 'click', 'hover'.
offsetArray[0, 0.125][x, y] offset from the trigger, measured in REM units.
placementString'bottom'Preferred placement relative to the trigger (see list below).
closeOnOutsideClickBooleantrueClose when a user clicks outside the trigger or content.
closeOnEscBooleantrueClose when the Escape key is pressed.
widthString/NumbernullExplicit menu width (CSS string or number in pixels).
matchTriggerWidthBooleantrueWhen true, auto-match the trigger width if width is unset.
menuContentClassArray[]Additional class names applied to the teleported menu element.
disabledBooleanfalsePrevent the trigger from opening the menu.
fixedXString''Overrides the calculated left position (any valid CSS length).
fixedYString''Overrides the calculated top position.
menuIdString''Adds IDs for trigger/content (e.g. {menuId}Trigger) to aid accessibility.
stopPropagationBooleantrueStops the trigger click from bubbling; set false to allow parent handlers.

Placement Options ​

OMenu accepts these placement strings: top, bottom, left, right, top-start, top-end, bottom-start, bottom-end, left-top, left-bottom, right-top, right-bottom. Collision detection can flip your requested placement automatically when the viewport would otherwise clip the menu.

Events ​

EventPayloadDescription
open-Emitted when menu opens
close-Emitted when menu closes

Slots ​

SlotDescription
triggerThe element that triggers the menu
contentThe menu content to display

Exposed Methods ​

The component exposes these methods via template refs:

MethodDescription
openMenu()Programmatically open the menu
closeMenu()Programmatically close the menu
toggleMenu()Toggle the menu open/closed state

Exposed Properties ​

PropertyTypeDescription
isOpenBooleanCurrent open/closed state of the menu
actualPlacementStringThe actual placement after collision detection

Features ​

Collision Detection ​

The menu automatically detects viewport boundaries and adjusts its position to prevent overflow. If the preferred placement would cause the menu to go outside the viewport, it will automatically flip to the opposite side.

Hover Support ​

When triggerType is set to 'hover', the menu opens on mouse enter and closes on mouse leave with a small delay to prevent accidental closing.

Responsive Positioning ​

The menu position updates automatically on window resize and scroll events to maintain proper positioning relative to the trigger element.

Teleport ​

Menu content teleports to document.body for consistent layering. Apply custom styles via menuContentClass if you need extra elevation, padding, or scroll tweaks.

Example Usage ​

vue
<template>
  <OMenu 
    ref="menuRef"
    trigger-type="click"
    placement="bottom-start"
    :width="300"
    :match-trigger-width="false"
    @open="handleOpen"
  >
    <template #trigger>
      <button>Open Menu</button>
    </template>
    <template #content>
      <div class="menu-items">
        <div class="menu-item">Item 1</div>
        <div class="menu-item">Item 2</div>
        <div class="menu-item">Item 3</div>
      </div>
    </template>
  </OMenu>
</template>

<script setup>
import { ref } from 'vue'

const menuRef = ref(null)

// Programmatic control
const openMenu = () => {
  menuRef.value.openMenu()
}

const handleOpen = () => {
  console.log('Menu opened')
}
</script>