Component

Context menu

<DomContextMenu>

A right-click menu built on the shared menu primitive.

Demo

Right-click menu

Context menus use the same DomMenu item model, including keyboard navigation and destructive tones.

Right click this panel to open the context menu.

Selected: none

Rows.vuevue
<script setup>
import { ref } from 'vue';
import { DomContextMenu } from '@getdom/studio/vue';

const selected = ref('none');
const items = [
	{ label: 'Open', value: 'open' },
	{ label: 'Rename', value: 'rename' },
	{ label: 'Duplicate', value: 'duplicate' },
	{ separator: true },
	{ label: 'Delete', value: 'delete', tone: 'danger' },
];
</script>

<template>
	<div class="w-full max-w-md space-y-3">
		<DomContextMenu :items="items" @select="selected = $event.value">
			<div class="rounded-2xl border border-dashed border-border bg-secondary/30 p-6 text-center text-sm text-muted-fg">
				Right click this panel to open the context menu.
			</div>
		</DomContextMenu>

		<p class="text-xs text-muted-fg">Selected: <code class="text-fg">{{ selected }}</code></p>
	</div>
</template>

Nested

Context menu with submenus

Use the same children array as DomMenu to create hoverable and keyboard-accessible nested context menu items.

Quarterly plan

Right click this row to open nested actions.

Live

Owner

Maya Patel

Status

In review

Updated

Today

Selected: none

Nested.vuevue
<script setup>
import { ref } from 'vue';
import { DomContextMenu } from '@getdom/studio/vue';

const selected = ref('none');
const items = [
	{ label: 'Open', value: 'open' },
	{ label: 'Rename', value: 'rename' },
	{ label: 'Duplicate', value: 'duplicate' },
	{
		label: 'Move to',
		value: 'move',
		children: [
			{ label: 'Inbox', value: 'move-inbox' },
			{ label: 'Archive', value: 'move-archive' },
			{ label: 'Projects', value: 'move-projects' },
		],
	},
	{
		label: 'Share',
		value: 'share',
		children: [
			{ label: 'Email', value: 'share-email' },
			{ label: 'SMS', value: 'share-sms' },
			{ label: 'Instagram', value: 'share-instagram' },
		],
	},
	{ separator: true },
	{ label: 'Delete', value: 'delete', tone: 'danger' },
];
</script>

<template>
	<div class="w-full max-w-lg space-y-3">
		<DomContextMenu :items="items" @select="selected = $event.value">
			<div class="overflow-hidden rounded-2xl border border-border bg-background text-sm shadow-sm">
				<div class="grid grid-cols-[1fr_auto] gap-4 border-b border-border skin-raised px-4 py-3 backdrop-blur">
					<div>
						<p class="font-medium text-fg">Quarterly plan</p>
						<p class="mt-1 text-xs text-muted-fg">Right click this row to open nested actions.</p>
					</div>
					<span class="self-start rounded-full bg-success/15 px-2.5 py-1 text-xs font-medium text-success">Live</span>
				</div>
				<div class="grid gap-2 p-4 text-muted-fg sm:grid-cols-3">
					<div>
						<p class="text-xs uppercase tracking-[0.14em]">Owner</p>
						<p class="mt-1 text-fg">Maya Patel</p>
					</div>
					<div>
						<p class="text-xs uppercase tracking-[0.14em]">Status</p>
						<p class="mt-1 text-fg">In review</p>
					</div>
					<div>
						<p class="text-xs uppercase tracking-[0.14em]">Updated</p>
						<p class="mt-1 text-fg">Today</p>
					</div>
				</div>
			</div>
		</DomContextMenu>

		<p class="text-xs text-muted-fg">Selected: <code class="text-fg">{{ selected }}</code></p>
	</div>
</template>

Reference

Props

Control props

NameTypeTSDefaultDescription
items*arrayArray<unknown>Context menu rows. Use children for nested menus.
widthstringstring'min-w-48'Tailwind width utility for the menu panel.
lockScrollbooleanbooleantrueLock browser scrolling while the context menu is open.
openOnContextMenubooleanbooleantrueOpen automatically when the default slot is right-clicked. Disable when opening from another component event.

Auto-generated from Context menu.props and inline _edit hints.

Events

NamePayloadDescription
@open({ event })Fired when the menu is opened.
@select({ value, item })Fired when a menu item is selected.

Names auto-detected from defineEmits and source emit() calls; payload and description from __doc.events when present.