Examples
Basic Usage
Open a menu with right click from a configured trigger area.
<div data-kt-context-menu="true" class="inline-flex">
<div
data-kt-context-menu-trigger="true"
class="kt-card border-dashed w-[360px] h-[180px] flex items-center justify-center text-muted-foreground text-sm select-none"
>
Right click inside this area
</div>
<div data-kt-context-menu-menu="true" class="kt-context-menu w-56 hidden">
<ul class="kt-context-menu-sub">
<li><button type="button" class="kt-context-menu-link">Open</button></li>
<li>
<button type="button" class="kt-context-menu-link">Rename</button>
</li>
<li>
<button type="button" class="kt-context-menu-link">Duplicate</button>
</li>
</ul>
</div>
</div>
Dismiss
Set data-kt-context-menu-dismiss="true" on action elements to close the menu hierarchy after click.
<div data-kt-context-menu="true" class="inline-flex">
<div
data-kt-context-menu-trigger="true"
class="kt-card border-dashed w-[360px] h-[180px] flex items-center justify-center text-muted-foreground text-sm select-none"
>
Right click and choose an action
</div>
<div data-kt-context-menu-menu="true" class="kt-context-menu w-60 hidden">
<ul class="kt-context-menu-sub">
<li>
<button
type="button"
class="kt-context-menu-link"
data-kt-context-menu-dismiss="true"
>
Edit file
</button>
</li>
<li>
<button
type="button"
class="kt-context-menu-link"
data-kt-context-menu-dismiss="true"
>
Copy path
</button>
</li>
<li class="kt-context-menu-separator"></li>
<li>
<button
type="button"
class="kt-context-menu-link text-destructive"
data-kt-context-menu-dismiss="true"
>
Delete
</button>
</li>
</ul>
</div>
</div>
Nest context menu roots to create submenu flyouts.
Placement
Use data-kt-context-menu-placement and data-kt-context-menu-placement-rtl to tune menu direction.
<div class="grid grid-cols-2 gap-4 max-w-[520px]">
<div
data-kt-context-menu="true"
data-kt-context-menu-placement="right-start"
class="inline-flex"
>
<div
data-kt-context-menu-trigger="true"
class="kt-card border-dashed w-full h-[110px] flex items-center justify-center text-xs text-muted-foreground select-none"
>
Top left
</div>
<div data-kt-context-menu-menu="true" class="kt-context-menu w-44 hidden">
<ul class="kt-context-menu-sub">
<li>
<button type="button" class="kt-context-menu-link">Inspect</button>
</li>
</ul>
</div>
</div>
<div
data-kt-context-menu="true"
data-kt-context-menu-placement="left-start"
class="inline-flex"
>
<div
data-kt-context-menu-trigger="true"
class="kt-card border-dashed w-full h-[110px] flex items-center justify-center text-xs text-muted-foreground select-none"
>
Top right
</div>
<div data-kt-context-menu-menu="true" class="kt-context-menu w-44 hidden">
<ul class="kt-context-menu-sub">
<li>
<button type="button" class="kt-context-menu-link">Inspect</button>
</li>
</ul>
</div>
</div>
</div>
With Modal
Context menus can be used inside KTModal content.
<div>
<button class="kt-btn" data-kt-modal-toggle="#context_menu_modal">
Open Modal
</button>
<div class="kt-modal" data-kt-modal="true" id="context_menu_modal">
<div class="kt-modal-content max-w-[420px] top-[12%]">
<div class="kt-modal-header">
<h3 class="kt-modal-title">Context Menu in Modal</h3>
<button
class="kt-modal-close"
aria-label="Close modal"
data-kt-modal-dismiss="#context_menu_modal"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-x"
aria-hidden="true"
>
<path d="M18 6 6 18"></path>
<path d="m6 6 12 12"></path>
</svg>
</button>
</div>
<div class="kt-modal-body flex justify-center min-h-56">
<div data-kt-context-menu="true" class="inline-flex">
<div
data-kt-context-menu-trigger="true"
class="kt-card border-dashed w-[280px] h-[140px] flex items-center justify-center text-muted-foreground text-sm select-none"
>
Right click here
</div>
<div
data-kt-context-menu-menu="true"
class="kt-context-menu w-56 hidden"
>
<ul class="kt-context-menu-sub">
<li>
<button
type="button"
class="kt-context-menu-link"
data-kt-context-menu-dismiss="true"
>
Save draft
</button>
</li>
<li>
<button
type="button"
class="kt-context-menu-link"
data-kt-context-menu-dismiss="true"
>
Share
</button>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
Keyboard
Use Escape to close opened menus. This variant shows keyboard-focused usage hints.
<div data-kt-context-menu="true" data-kt-context-menu-keyboard="true">
<div
data-kt-context-menu-trigger="true"
tabindex="0"
class="kt-card border-dashed w-[420px] h-[180px] flex flex-col items-center justify-center gap-2 text-muted-foreground text-sm select-none outline-none focus:ring-2 focus:ring-primary/30"
>
<span>Right click to open context menu</span
><span class="text-xs">Press Esc to close</span>
</div>
<div data-kt-context-menu-menu="true" class="kt-context-menu w-56 hidden">
<ul class="kt-context-menu-sub">
<li>
<button type="button" class="kt-context-menu-link">New file</button>
</li>
<li>
<button type="button" class="kt-context-menu-link">New folder</button>
</li>
<li class="kt-context-menu-separator"></li>
<li>
<button type="button" class="kt-context-menu-link">
Command palette
</button>
</li>
<li>
<button
type="button"
class="kt-context-menu-link"
data-kt-context-menu-dismiss="true"
>
Close menu
</button>
</li>
</ul>
</div>
</div>
Disabled Items
Use native disabled state to keep unavailable actions visible but non-interactive.
<div data-kt-context-menu="true" class="inline-flex">
<div
data-kt-context-menu-trigger="true"
class="kt-card border-dashed w-[380px] h-[180px] flex items-center justify-center text-muted-foreground text-sm select-none"
>
Right click for disabled states
</div>
<div data-kt-context-menu-menu="true" class="kt-context-menu w-56 hidden">
<ul class="kt-context-menu-sub">
<li>
<button type="button" class="kt-context-menu-link">Open project</button>
</li>
<li>
<button type="button" class="kt-context-menu-link">Open recent</button>
</li>
<li class="kt-context-menu-separator"></li>
<li>
<button type="button" class="kt-context-menu-link" disabled="">
Share workspace (pro)
</button>
</li>
<li>
<button type="button" class="kt-context-menu-link" disabled="">
Publish package
</button>
</li>
<li>
<button type="button" class="kt-context-menu-link">Settings</button>
</li>
</ul>
</div>
</div>
Icons
Use icon-leading actions for improved scanability in dense context menus.
<div data-kt-context-menu="true" class="inline-flex">
<div
data-kt-context-menu-trigger="true"
class="kt-card border-dashed w-[380px] h-[180px] flex items-center justify-center text-muted-foreground text-sm select-none"
>
Right click for icon menu
</div>
<div data-kt-context-menu-menu="true" class="kt-context-menu w-56 hidden">
<ul class="kt-context-menu-sub">
<li>
<button type="button" class="kt-context-menu-link">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-folder-open size-4 text-muted-foreground"
aria-hidden="true"
>
<path
d="m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2"
></path></svg
>Open
</button>
</li>
<li>
<button type="button" class="kt-context-menu-link">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-file-text size-4 text-muted-foreground"
aria-hidden="true"
>
<path
d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"
></path>
<path d="M14 2v5a1 1 0 0 0 1 1h5"></path>
<path d="M10 9H8"></path>
<path d="M16 13H8"></path>
<path d="M16 17H8"></path></svg
>Preview
</button>
</li>
<li>
<button type="button" class="kt-context-menu-link">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-pencil size-4 text-muted-foreground"
aria-hidden="true"
>
<path
d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
></path>
<path d="m15 5 4 4"></path></svg
>Rename
</button>
</li>
<li>
<button type="button" class="kt-context-menu-link">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-copy size-4 text-muted-foreground"
aria-hidden="true"
>
<rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect>
<path
d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"
></path></svg
>Duplicate
</button>
</li>
<li>
<button type="button" class="kt-context-menu-link">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-share2 lucide-share-2 size-4 text-muted-foreground"
aria-hidden="true"
>
<circle cx="18" cy="5" r="3"></circle>
<circle cx="6" cy="12" r="3"></circle>
<circle cx="18" cy="19" r="3"></circle>
<line x1="8.59" x2="15.42" y1="13.51" y2="17.49"></line>
<line x1="15.41" x2="8.59" y1="6.51" y2="10.49"></line></svg
>Share
</button>
</li>
<li class="kt-context-menu-separator"></li>
<li>
<button type="button" class="kt-context-menu-link text-destructive">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-trash2 lucide-trash-2 size-4"
aria-hidden="true"
>
<path d="M10 11v6"></path>
<path d="M14 11v6"></path>
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"></path>
<path d="M3 6h18"></path>
<path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg
>Delete
</button>
</li>
</ul>
</div>
</div>
Shortcut Hints
Display keyboard shortcut hints on the right side of each action.
<div data-kt-context-menu="true" class="inline-flex">
<div
data-kt-context-menu-trigger="true"
class="kt-card border-dashed w-[400px] h-[180px] flex items-center justify-center text-muted-foreground text-sm select-none"
>
Right click for shortcut hints
</div>
<div data-kt-context-menu-menu="true" class="kt-context-menu w-60 hidden">
<ul class="kt-context-menu-sub">
<li>
<button type="button" class="kt-context-menu-link">
Copy<span
class="ms-auto text-[11px] tracking-widest text-muted-foreground"
>CMD+C</span
>
</button>
</li>
<li>
<button type="button" class="kt-context-menu-link">
Cut<span
class="ms-auto text-[11px] tracking-widest text-muted-foreground"
>CMD+X</span
>
</button>
</li>
<li>
<button type="button" class="kt-context-menu-link">
Paste<span
class="ms-auto text-[11px] tracking-widest text-muted-foreground"
>CMD+V</span
>
</button>
</li>
<li class="kt-context-menu-separator"></li>
<li>
<button type="button" class="kt-context-menu-link">
Rename<span
class="ms-auto text-[11px] tracking-widest text-muted-foreground"
>F2</span
>
</button>
</li>
<li>
<button type="button" class="kt-context-menu-link text-destructive">
Delete<span
class="ms-auto text-[11px] tracking-widest text-muted-foreground"
>SHIFT+DEL</span
>
</button>
</li>
</ul>
</div>
</div>
Component API
Options
| Option | Type | Default | Description |
|---|
data-kt-context-menu-zindex | number | 105 | Controls stacking level when menu is shown. |
data-kt-context-menu-placement | enum | |
Selectors
| Name | Description |
|---|
data-kt-context-menu="true" | Auto-initializes a context menu root. |
data-kt-context-menu-trigger="true" | Trigger element that receives contextmenu interaction. |
data-kt-context-menu-target="#selector" | Optional selector for external trigger target. |
|
Methods
| Method | Description |
|---|
new KTContextMenu(element, options) | Creates a context menu instance for the root element. |
showAt(x, y) | Opens the menu at viewport coordinates. |
showAtEvent(event) | Opens from a MouseEvent pointer coordinate. |
|
import {
KTContextMenu,
type KTContextMenuConfigInterface,
type KTContextMenuInterface,
} from '@keenthemes/ktui';
const root = document.querySelector<HTMLElement>('[data-kt-context-menu]');
if (!root) throw new Error('Missing context menu root');
const options: KTContextMenuConfigInterface = {
placement: 'right-start',
placementRtl: 'left-start',
};
const contextMenu: KTContextMenuInterface =
KTContextMenu.getOrCreateInstance(root, options);
Utilities
| Method | Description |
|---|
KTContextMenu.init() | Initializes all context menus in the document. |
KTContextMenu.createInstances() | Initializes new context menus added to the DOM. |
KTContextMenu.getInstance(element) | Returns context menu instance for element context. |
|
Events
| Event | Description |
|---|
show | Fires before menu opens; payload can cancel. |
shown | Fires after menu open transition completes. |
hide | Fires before menu closes; payload can cancel. |
|