Context Menu <mv-context-menu>
Menu contextuel ouvert au niveau du pointeur (clic droit), par appui long sur écran tactile ou au clavier (Maj+F10 / touche Menu) ; réutilise le moteur et les styles de Menu, y compris l’animation data-motion="glide".
Catégorie Superpositions Type Web Component (<mv-context-menu>) Statut stable Installe aussi menu , popover Keywords context-menu, right-click, long-press, menu, submenu
When to use
Items in a file list, canvas or table need actions on right-click or touch long-press Power users expect contextual actions at the pointer, with keyboard access through Shift+F10 or the Menu key
Avoid when
The actions are hidden only behind right-click with no visible trigger to discover them → use Menu instead The area is plain reading content where users expect the browser menu for copy and search
Obtenir Context Menu. Inclus dans toutes les offres : le Pro pack contient les 317 composants, avec la CLI et le serveur MCP utilisés ci-dessous.
Voir les offres
Installation
node scripts/add.mjs context-menu --out ./src/marvelous
Agent IA avec le serveur MCP de Marvelous UI : install_components({ slugs: ["context-menu"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Fichiers copiés (dépendances comprises) : tokens/tokens.css, core/base.css, core/dismiss.js, core/dom.js, core/element.js, core/focus.js, core/motion.js, core/position.js, components/context-menu/context-menu.js, components/context-menu/context-menu.css, components/menu/menu.js, components/menu/menu.css, components/popover/popover.js, components/popover/popover.css.
Utilisation
Balisage de référence : partez de celui-ci et personnalisez-le avec les attributs, data-* et les variables CSS :
<div id="ctx-demo" style="display:grid;gap:1rem;width:min(26rem,100%)">
<mv-context-menu>
<div class="mv-context-menu-area" aria-label="Layer “Hero banner”" style="min-height:11rem">
<svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="opacity:.6"><path d="m12 3 9 5-9 5-9-5z"/><path d="m3 13 9 5 9-5"/></svg>
<strong style="color:var(--mv-fg);font-weight:500">Right-click the layer</strong>
<span style="font-size:.75rem">Long-press on mobile · Shift + F10 on keyboard</span>
</div>
<div data-content style="--mv-menu-width:15rem">
<button role="menuitem" value="copy">Copy <span class="mv-menu-shortcut">⌘C</span></button>
<button role="menuitem" value="paste" disabled>Paste <span class="mv-menu-shortcut">⌘V</span></button>
<button role="menuitem" value="duplicate">Duplicate <span class="mv-menu-shortcut">⌘D</span></button>
<div data-submenu>
<button role="menuitem">Arrange</button>
<div data-content style="--mv-menu-width:13rem">
<button role="menuitem" value="bring-to-front">Bring to front <span class="mv-menu-shortcut">⇧⌘]</span></button>
<button role="menuitem" value="bring-forward">Bring forward <span class="mv-menu-shortcut">⌘]</span></button>
<button role="menuitem" value="send-backward">Send backward <span class="mv-menu-shortcut">⌘[</span></button>
<button role="menuitem" value="send-to-back">Send to back <span class="mv-menu-shortcut">⇧⌘[</span></button>
</div>
</div>
<hr>
<button role="menuitemcheckbox" value="lock">Lock <span class="mv-menu-shortcut">⇧⌘L</span></button>
<button role="menuitemcheckbox" value="hide">Hide <span class="mv-menu-shortcut">⇧⌘H</span></button>
<hr>
<div role="group" data-name="blend">
<div class="mv-menu-label" data-inset>Blend mode</div>
<button role="menuitemradio" value="normal" aria-checked="true">Normal</button>
<button role="menuitemradio" value="multiply">Multiply</button>
<button role="menuitemradio" value="overlay">Overlay</button>
</div>
<hr>
<button role="menuitem" value="delete" data-variant="destructive">Delete <span class="mv-menu-shortcut">⌫</span></button>
</div>
</mv-context-menu>
<mv-context-menu data-motion="glide">
<div class="mv-context-menu-area" aria-label="File “q3-report.pdf”" style="min-height:6rem">
<strong style="color:var(--mv-fg);font-weight:500">data-motion="glide"</strong>
<span style="font-size:.75rem">The menu blooms from the pointer, the highlight glides</span>
</div>
<div data-content style="--mv-menu-width:13rem">
<button role="menuitem" value="open">Open <span class="mv-menu-shortcut">↵</span></button>
<button role="menuitem" value="quick-look">Quick Look <span class="mv-menu-shortcut">␣</span></button>
<div data-submenu>
<button role="menuitem">Open with</button>
<div data-content>
<button role="menuitem" value="app-reader">PDF reader</button>
<button role="menuitem" value="app-browser">Browser</button>
</div>
</div>
<hr>
<button role="menuitem" value="rename">Rename</button>
<button role="menuitem" value="delete" data-variant="destructive">Delete <span class="mv-menu-shortcut">⌫</span></button>
</div>
</mv-context-menu>
<p data-role="out" aria-live="polite" style="margin:0;text-align:center;font-size:.8125rem;color:var(--mv-fg-muted)">No action yet.</p>
</div>
<script type="module">
const root = document.getElementById("ctx-demo");
const out = root.querySelector('[data-role="out"]');
root.addEventListener("mv-select", (e) => {
const { label, checked, group } = e.detail;
out.textContent = group ? `Blend: ${label}` : checked === undefined ? `Action: ${label}` : `${label}: ${checked ? "on" : "off"}`;
});
</script>
API
Attributes
Name Type Description disabledboolean Lets the browser’s native menu through. data-motion"glide" Same option as mv-menu: the panel blooms from the click point, the highlight glides between items, submenus slide in.
Properties
Name Type Description isOpenboolean Read-only. menuMenuPanel Instance of the engine shared with mv-menu.
Methods
Name Description openAt(x, y, { focus })Opens at viewport coordinates; focus = "first" | "panel". hide({ focus })Closes; focus=true returns focus to the element that was active before opening (or to the area).
Events
Name Description mv-selectCancelable. detail: { value, label, item, checked?, group? } (same as mv-menu). mv-opendetail: { x, y }. mv-closeAfter closing.
Content structure
Name Description first childTarget area; made focusable (tabindex=0) if it isn’t. Its aria-label names the menu. [data-content]Panel: same markup as mv-menu (menuitem, checkbox, radio, [data-submenu], <hr>, .mv-menu-label, .mv-menu-shortcut).
CSS classes
Name Description mv-context-menu-areaReady-made dashed area (visual feedback during long-press).
CSS variables
Name Description --mv-menu-*All Menu variables apply (width, highlight, background, radius).
Accessibility
role=menu panel (APG “Menu” pattern) with full navigation: ↑↓ Home/End, typeahead, → / ← for submenus, Escape and Tab close. Keyboard opening via Shift+F10 or the Menu key from the focusable area (focus on the first item); focus then returns to the original element.