Overview
The Context Menu component displays a contextual menu when right-clicking an element. Supports items with icons, avatars, keyboard shortcuts, checkboxes, and nested submenus.
Basic Usage
<template>
<UContextMenu :items="menuItems">
<template #default>
<div class="p-8 border rounded">
Right-click here
</div>
</template>
</UContextMenu>
</template>
<script setup>
const menuItems = [
{
label: 'Edit',
icon: 'i-lucide-pencil',
onSelect: () => console.log('Edit clicked')
},
{
label: 'Delete',
icon: 'i-lucide-trash',
color: 'error',
onSelect: () => console.log('Delete clicked')
}
]
</script>
Props
Array of menu items to display. See Item Properties below.
size
'xs' | 'sm' | 'md' | 'lg' | 'xl'
default:"'md'"
The size of the menu and its items.
checkedIcon
string
default:"appConfig.ui.icons.check"
The icon displayed when an item is checked. Accepts Iconify icon names.
loadingIcon
string
default:"appConfig.ui.icons.loading"
The icon displayed when an item is loading. Accepts Iconify icon names.
externalIcon
boolean | string
default:"appConfig.ui.icons.external"
The icon displayed when the item is an external link. Set to false to hide.
Additional props passed to the menu content element.
portal
boolean | string | HTMLElement
default:"true"
Render the menu in a portal.
The modality of the menu.
The key used to get the label from the item.
descriptionKey
string
default:"'description'"
The key used to get the description from the item.
Disable the entire context menu.
CSS class for styling the trigger element.
Theme customization object for component slots.
Events
Emitted when the open state changes.
Slots
The trigger element that opens the context menu on right-click.
item
{ item: ContextMenuItem, active: boolean, index: number, ui: object }
Customize the entire item rendering.
item-leading
{ item: ContextMenuItem, active: boolean, index: number, ui: object }
Customize the leading section (icon/avatar) of items.
item-label
{ item: ContextMenuItem, active: boolean, index: number }
Customize the label section of items.
item-description
{ item: ContextMenuItem, active: boolean, index: number }
Customize the description section of items.
item-trailing
{ item: ContextMenuItem, active: boolean, index: number, ui: object }
Customize the trailing section (keyboard shortcuts/icons) of items.
Content rendered at the top of the menu.
Content rendered at the bottom of the menu.
Item Properties
Each item in the items array can have the following properties:
The text label for the item.
Optional description text shown below the label.
Iconify icon name to display before the label.
Avatar to display instead of an icon.
Color variant for the item.
kbds
KbdProps['value'][] | KbdProps[]
Keyboard shortcuts to display on the right.
type
'label' | 'separator' | 'link' | 'checkbox'
default:"'link'"
The item type.
Custom slot name for this item.
Show loading state for the item.
Checked state for checkbox items.
Callback fired when the item is selected.
onUpdateChecked
(checked: boolean) => void
Callback fired when checkbox state changes.
Examples
<template>
<UContextMenu :items="menuItems">
<template #default>
<div class="p-8 border rounded">
Right-click for nested menu
</div>
</template>
</UContextMenu>
</template>
<script setup>
const menuItems = [
{
label: 'File',
icon: 'i-lucide-file',
children: [
{ label: 'New', icon: 'i-lucide-file-plus' },
{ label: 'Open', icon: 'i-lucide-folder-open' },
{ type: 'separator' },
{ label: 'Save', icon: 'i-lucide-save', kbds: ['meta', 'S'] }
]
},
{
label: 'Edit',
icon: 'i-lucide-pencil',
children: [
{ label: 'Cut', icon: 'i-lucide-scissors', kbds: ['meta', 'X'] },
{ label: 'Copy', icon: 'i-lucide-copy', kbds: ['meta', 'C'] },
{ label: 'Paste', icon: 'i-lucide-clipboard', kbds: ['meta', 'V'] }
]
}
]
</script>
With Checkboxes
<template>
<UContextMenu :items="menuItems">
<template #default>
<div class="p-8 border rounded">
Right-click for options
</div>
</template>
</UContextMenu>
</template>
<script setup>
const showToolbar = ref(true)
const showSidebar = ref(false)
const menuItems = computed(() => [
{
label: 'Show Toolbar',
type: 'checkbox',
checked: showToolbar.value,
onUpdateChecked: (val) => showToolbar.value = val
},
{
label: 'Show Sidebar',
type: 'checkbox',
checked: showSidebar.value,
onUpdateChecked: (val) => showSidebar.value = val
}
])
</script>
With Separators and Labels
<template>
<UContextMenu :items="menuItems">
<template #default>
<div class="p-8 border rounded">
Right-click here
</div>
</template>
</UContextMenu>
</template>
<script setup>
const menuItems = [
{ type: 'label', label: 'Actions' },
{ label: 'Edit', icon: 'i-lucide-pencil' },
{ label: 'Duplicate', icon: 'i-lucide-copy' },
{ type: 'separator' },
{ type: 'label', label: 'Danger Zone' },
{ label: 'Delete', icon: 'i-lucide-trash', color: 'error' }
]
</script>
With User Avatar
<template>
<UContextMenu :items="menuItems">
<template #default>
<div class="p-8 border rounded">
Right-click for user menu
</div>
</template>
</UContextMenu>
</template>
<script setup>
const menuItems = [
{
label: 'John Doe',
description: '[email protected]',
avatar: { src: '/avatar.jpg' }
},
{ type: 'separator' },
{ label: 'Profile', icon: 'i-lucide-user' },
{ label: 'Settings', icon: 'i-lucide-settings' },
{ type: 'separator' },
{ label: 'Logout', icon: 'i-lucide-log-out', color: 'error' }
]
</script>
With Loading State
<template>
<UContextMenu :items="menuItems">
<template #default>
<div class="p-8 border rounded">
Right-click to see loading
</div>
</template>
</UContextMenu>
</template>
<script setup>
const isLoading = ref(false)
const menuItems = computed(() => [
{
label: 'Refresh',
icon: 'i-lucide-refresh-cw',
loading: isLoading.value,
onSelect: async () => {
isLoading.value = true
await new Promise(resolve => setTimeout(resolve, 2000))
isLoading.value = false
}
}
])
</script>
With External Links
<template>
<UContextMenu :items="menuItems">
<template #default>
<div class="p-8 border rounded">
Right-click for links
</div>
</template>
</UContextMenu>
</template>
<script setup>
const menuItems = [
{
label: 'Documentation',
icon: 'i-lucide-book',
to: 'https://nuxt.com',
target: '_blank'
},
{
label: 'GitHub',
icon: 'i-lucide-github',
to: 'https://github.com/nuxt/ui',
target: '_blank'
}
]
</script>