Context menu (mode: "context")

Right-click anywhere in the box below. On touch devices, press and hold. The menu opens at the pointer with icons, disabled items, separators, and nested submenus.

Right-click anywhere in this box
HTML
<link rel="stylesheet" href="hcg-context-menu.css">

<div id="area">Right-click anywhere in this box</div>

<script src="hcg-context-menu.js"></script>
JavaScript
hcgContextMenu({
  target: "#area",
  mode: "context",
  onSelect: function (item) {
    console.log("selected:", item.value || item.label);
  },
  items: [
    { label: "Cut",   icon: "✂",  value: "cut",  action: function () { alert("Cut"); } },
    { label: "Copy",  icon: "📋", value: "copy", action: function () { alert("Copy"); } },
    { label: "Paste", icon: "📄", value: "paste", disabled: true },
    { separator: true },
    { label: "Share", icon: "🔗", submenu: [
        { label: "Email", action: function () { alert("Email"); } },
        { label: "Link",  action: function () { alert("Link"); } },
        { label: "More", submenu: [
            { label: "Twitter", action: function () { alert("Twitter"); } },
            { label: "Reddit",  action: function () { alert("Reddit"); } }
        ] }
    ] },
    { separator: true },
    { label: "Delete", icon: "🗑", action: function () { alert("Delete"); } }
  ]
});

Dropdown menu (mode: "dropdown")

Click the button to open a menu below it. Ideal for navigation buttons and action menus.

HTML
<button id="menuBtn" type="button">Open dropdown menu</button>
JavaScript
hcgContextMenu({
  target: "#menuBtn",
  mode: "dropdown",
  items: [
    { label: "Profile",  action: function () { alert("Profile"); } },
    { label: "Settings", action: function () { alert("Settings"); } },
    { separator: true },
    { label: "Sign out", action: function () { alert("Sign out"); } }
  ]
});

Long menu - maxHeight scroll

Right-click this box. With maxHeight: 260, a long list scrolls inside the panel instead of overflowing the viewport.

Right-click for a 30-item menu
HTML
<div id="long-area">Right-click for a 30-item menu</div>
JavaScript
function longItems() {
  var arr = [{ header: "Long list" }];
  for (var i = 1; i <= 30; i++) {
    (function (n) {
      arr.push({ label: "Item " + n, action: function () { alert("Item " + n); } });
    })(i);
  }
  return arr;
}

hcgContextMenu({
  target: "#long-area",
  mode: "context",
  maxHeight: 260,
  items: longItems()
});

Long dropdown - flip above

Click the button near the bottom of the page. When there is not enough room below, the menu flips above the button and scrolls.

HTML
<button id="long-dropdown-btn" type="button">Open long dropdown</button>
JavaScript
hcgContextMenu({
  target: "#long-dropdown-btn",
  mode: "dropdown",
  maxHeight: 300,
  items: longItems()
});

Long text labels - ellipsis

Long labels truncate with an ellipsis. Hover an item to see the full text in a native tooltip.

Right-click for very long item labels
HTML
<div id="longtext-area">Right-click for very long item labels</div>
JavaScript
hcgContextMenu({
  target: "#longtext-area",
  mode: "context",
  items: [
    { header: "Document actions" },
    { label: "Export this document as a PDF and email it to the team", icon: "📄", action: function () { alert("Export"); } },
    { label: "Duplicate this item into the shared workspace folder", icon: "📋", action: function () { alert("Duplicate"); } },
    { separator: true },
    { label: "Rename", icon: "✎", action: function () { alert("Rename"); } },
    { label: "Move to another very long destination folder name here", submenu: [
        { label: "A really long submenu item label that also overflows", action: function () { alert("Sub 1"); } },
        { label: "Short one", action: function () { alert("Sub 2"); } }
    ] }
  ]
});

HTML labels - formatting

Use the html field to render trusted markup (bold, italic, colors, badges). Plain label text is always escaped.

Right-click for HTML-formatted labels
HTML
<div id="html-area">Right-click for HTML-formatted labels</div>
JavaScript
hcgContextMenu({
  target: "#html-area",
  mode: "context",
  items: [
    { html: "<strong>Profile</strong>", action: function () { alert("Profile"); } },
    { html: "<i>Copy</i>", action: function () { alert("Copy"); } },
    { html: "Status: <span style='color:#1a9d4b'>Online</span>", action: function () { alert("Status"); } },
    { separator: true },
    { html: "Upgrade <span style='background:#2563eb;color:#fff;border-radius:4px;padding:1px 6px;font-size:11px;'>PRO</span>", action: function () { alert("Upgrade"); } },
    { label: "<b>plain label, not rendered</b>", action: function () { alert("Plain"); } }
  ]
});

Menu from HTML markup

Define items in a hidden <ul> and pass it with the source option. Handle clicks centrally with onSelect.

Right-click this box (menu built from a hidden <ul>)
  • Edit
  • Copy
  • Paste
HTML
<div id="markup-area">Right-click this box</div>

<ul id="markupMenu">
  <li data-hcg-icon="&#9998;" data-hcg-value="edit">Edit</li>
  <li data-hcg-icon="&#128203;" data-hcg-value="copy">Copy</li>
  <li class="hcg-context-menu-separator"></li>
  <li data-hcg-disabled data-hcg-value="paste">Paste</li>
</ul>
JavaScript
hcgContextMenu({
  target: "#markup-area",
  source: "#markupMenu",
  onSelect: function (item) { console.log("markup:", item.value); }
});