Appearance
Menu API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
triggerType | String | 'click' | How the menu opens. Accepts 'click' or 'hover'. |
offset | Array | [0, 0.125] | [x, y] offset, expressed in REM units, applied to the computed position. |
placement | String | 'bottom' | Preferred placement relative to the trigger (see list below). |
closeOnOutsideClick | Boolean | true | Close when the user clicks outside the trigger/menu. |
closeOnEsc | Boolean | true | Close when the Escape key is pressed. |
width | String/Number | null | Explicit menu width (CSS string or number in pixels). |
matchTriggerWidth | Boolean | true | Sync the menu width with the trigger when width is not provided. |
menuContentClass | Array | [] | Additional class names applied to the floating menu element. |
disabled | Boolean | false | Prevents the trigger from toggling the menu. |
fixedX | String | '' | Override the computed left position (any CSS length/percentage). |
fixedY | String | '' | Override the computed top position (any CSS length/percentage). |
menuId | String | '' | Adds deterministic IDs ({menuId}Trigger / {menuId}Content) for accessibility. |
stopPropagation | Boolean | true | Stops 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
| Event | Payload | Description |
|---|---|---|
open | - | Fired after the menu opens. |
close | - | Fired after the menu closes. |
Slots
| Slot | Description |
|---|---|
trigger | The interactive element that toggles the menu. Receives { isOpen }. |
content | The floating menu content. |
Exposed Methods
| Method | Description |
|---|---|
openMenu() | Programmatically open the menu. |
closeMenu() | Programmatically close the menu. |
toggleMenu() | Toggle the open/closed state. |
Exposed Properties
| Property | Type | Description |
|---|---|---|
isOpen | Boolean | Current open state of the menu. |
actualPlacement | String | Final 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
| Prop | Type | Default | Description |
|---|---|---|---|
triggerType | String | 'click' | How to open the menu. Options: 'click', 'hover'. |
offset | Array | [0, 0.125] | [x, y] offset from the trigger, measured in REM units. |
placement | String | 'bottom' | Preferred placement relative to the trigger (see list below). |
closeOnOutsideClick | Boolean | true | Close when a user clicks outside the trigger or content. |
closeOnEsc | Boolean | true | Close when the Escape key is pressed. |
width | String/Number | null | Explicit menu width (CSS string or number in pixels). |
matchTriggerWidth | Boolean | true | When true, auto-match the trigger width if width is unset. |
menuContentClass | Array | [] | Additional class names applied to the teleported menu element. |
disabled | Boolean | false | Prevent the trigger from opening the menu. |
fixedX | String | '' | Overrides the calculated left position (any valid CSS length). |
fixedY | String | '' | Overrides the calculated top position. |
menuId | String | '' | Adds IDs for trigger/content (e.g. {menuId}Trigger) to aid accessibility. |
stopPropagation | Boolean | true | Stops 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
| Event | Payload | Description |
|---|---|---|
open | - | Emitted when menu opens |
close | - | Emitted when menu closes |
Slots
| Slot | Description |
|---|---|
trigger | The element that triggers the menu |
content | The menu content to display |
Exposed Methods
The component exposes these methods via template refs:
| Method | Description |
|---|---|
openMenu() | Programmatically open the menu |
closeMenu() | Programmatically close the menu |
toggleMenu() | Toggle the menu open/closed state |
Exposed Properties
| Property | Type | Description |
|---|---|---|
isOpen | Boolean | Current open/closed state of the menu |
actualPlacement | String | The 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>