Overlays
ContextMenu
Display a menu that appears on right click.
Usage
Right click here
<script setup>
const { x, y } = useMouse()
const { y: windowY } = useWindowScroll()
const isOpen = ref(false)
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
function onContextMenu () {
const top = unref(y) - unref(windowY)
const left = unref(x)
virtualElement.value.getBoundingClientRect = () => ({
width: 0,
height: 0,
top,
left
})
isOpen.value = true
}
</script>
<template>
<div class="w-full" @contextmenu.prevent="onContextMenu">
<Placeholder class="h-96 select-none w-full flex items-center justify-center">
Right click here
</Placeholder>
<UContextMenu v-model="isOpen" :virtual-element="virtualElement">
<div class="p-4">
Menu
</div>
</UContextMenu>
</div>
</template>
Popper
Use the popper
prop to customize the popper instance.
Arrow
Right click here
<script setup>
const { x, y } = useMouse()
const { y: windowY } = useWindowScroll()
const isOpen = ref(false)
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
function onContextMenu () {
const top = unref(y) - unref(windowY)
const left = unref(x)
virtualElement.value.getBoundingClientRect = () => ({
width: 0,
height: 0,
top,
left
})
isOpen.value = true
}
</script>
<template>
<div class="w-full" @contextmenu.prevent="onContextMenu">
<Placeholder class="h-96 select-none w-full flex items-center justify-center">
Right click here
</Placeholder>
<UContextMenu v-model="isOpen" :virtual-element="virtualElement" :popper="{ arrow: true, placement: 'right' }">
<div class="p-4">
Menu
</div>
</UContextMenu>
</div>
</template>
Placement
Right click here
<script setup>
const { x, y } = useMouse()
const { y: windowY } = useWindowScroll()
const isOpen = ref(false)
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
function onContextMenu () {
const top = unref(y) - unref(windowY)
const left = unref(x)
virtualElement.value.getBoundingClientRect = () => ({
width: 0,
height: 0,
top,
left
})
isOpen.value = true
}
</script>
<template>
<div class="w-full" @contextmenu.prevent="onContextMenu">
<Placeholder class="h-96 select-none w-full flex items-center justify-center">
Right click here
</Placeholder>
<UContextMenu v-model="isOpen" :virtual-element="virtualElement" :popper="{ placement: 'right-start' }">
<div class="p-4">
Menu
</div>
</UContextMenu>
</div>
</template>
Offset
Right click here
<script setup>
const { x, y } = useMouse()
const { y: windowY } = useWindowScroll()
const isOpen = ref(false)
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
function onContextMenu () {
const top = unref(y) - unref(windowY)
const left = unref(x)
virtualElement.value.getBoundingClientRect = () => ({
width: 0,
height: 0,
top,
left
})
isOpen.value = true
}
</script>
<template>
<div class="w-full" @contextmenu.prevent="onContextMenu">
<Placeholder class="h-96 select-none w-full flex items-center justify-center">
Right click here
</Placeholder>
<UContextMenu v-model="isOpen" :virtual-element="virtualElement" :popper="{ offset: 0 }">
<div class="p-4">
Menu
</div>
</UContextMenu>
</div>
</template>
Props
virtualElementrequired
Record<string, any>
ui
{}
{}
popper
PopperOptions
{}
modelValue
boolean
false
Config
{
"wrapper": "relative",
"container": "z-20 group",
"width": "",
"background": "bg-white dark:bg-gray-900",
"shadow": "shadow-lg",
"rounded": "rounded-md",
"ring": "ring-1 ring-gray-200 dark:ring-gray-800",
"base": "overflow-hidden focus:outline-none relative",
"transition": {
"enterActiveClass": "transition ease-out duration-200",
"enterFromClass": "opacity-0 translate-y-1",
"enterToClass": "opacity-100 translate-y-0",
"leaveActiveClass": "transition ease-in duration-150",
"leaveFromClass": "opacity-100 translate-y-0",
"leaveToClass": "opacity-0 translate-y-1"
},
"popper": {
"placement": "bottom-start",
"scroll": false
},
"arrow": {
"base": "invisible before:visible before:block before:rotate-45 before:z-[-1] before:w-2 before:h-2",
"ring": "before:ring-1 before:ring-gray-200 dark:before:ring-gray-800",
"rounded": "before:rounded-sm",
"background": "before:bg-gray-200 dark:before:bg-gray-800",
"shadow": "before:shadow",
"placement": "group-data-[popper-placement*=\"right\"]:-left-1 group-data-[popper-placement*=\"left\"]:-right-1 group-data-[popper-placement*=\"top\"]:-bottom-1 group-data-[popper-placement*=\"bottom\"]:-top-1"
}
}