npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mapbox-gl-contextmenu

v1.6.0

Published

A contextmenu plugin for Mapbox GL JS

Readme

mapbox-gl-contextmenu

A context menu plugin for Mapbox GL JS and MapLibre GL JS.

Features

  • Context menus for the entire map or scoped to specific layers.
  • Menu items, section labels, separators, and nested submenus.
  • Customizable items with start/end content slots.
  • Click handlers receive map event data.
  • Full keyboard navigation.
  • Light and dark themes.

Table of Contents

Installation

npm

npm install mapbox-gl-contextmenu

CDN

<link
  rel="stylesheet"
  href="https://unpkg.com/mapbox-gl-contextmenu@1/dist/style.css"
/>
<script src="https://unpkg.com/mapbox-gl-contextmenu@1/dist/index.umd.js"></script>

Or using jsDelivr:

<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/mapbox-gl-contextmenu@1/dist/style.css"
/>
<script src="https://cdn.jsdelivr.net/npm/mapbox-gl-contextmenu@1/dist/index.umd.js"></script>

Usage

Using modules

import mapboxgl from "mapbox-gl";
import { MapboxContextMenu, ContextMenuItem } from "mapbox-gl-contextmenu";
import "mapbox-gl-contextmenu/style.css";

const map = new mapboxgl.Map({
  /* ... */
});

const menu = new MapboxContextMenu({ theme: "auto", width: 180 });

const centerItem = new ContextMenuItem({
  label: "Center map here",
  start: { className: "fa-solid fa-crosshairs" }
});

centerItem.on("click", ({ map, lngLat }) => {
  map.flyTo({ center: [lngLat.lng, lngLat.lat] });
});

menu.addItem(centerItem);
menu.addTo(map);

Using a CDN

When using the UMD build via a script tag, the library extends the mapboxgl global object:

<script>
  const { MapboxContextMenu, ContextMenuItem } = mapboxgl;

  const menu = new MapboxContextMenu({ theme: "auto", width: 180 });

  const centerItem = new ContextMenuItem({
    label: "Center map here",
    start: { className: "fa-solid fa-crosshairs" }
  });

  centerItem.on("click", ({ map, lngLat }) => {
    map.flyTo({ center: [lngLat.lng, lngLat.lat] });
  });

  menu.addItem(centerItem);
  menu.addTo(map);
</script>

API

For complete API documentation, see the API Reference.

MapboxContextMenu

The main context menu class for Mapbox GL JS and MapLibre GL JS maps.

const menu = new MapboxContextMenu(options);

Options:

  • theme - theme to use: 'light', 'dark', or 'auto' (follows system preference). Defaults to 'auto'.
  • width - menu width as a CSS value (e.g., '200px') or number in pixels.
  • className - custom CSS class name for the menu element.

Methods:

  • addItem(item) - add a menu item.
  • insertItem(index, item) - insert a menu item at a specific index.
  • removeItem(item) - remove a menu item.
  • addTo(map, target?) - add the menu to a map. Optionally restrict to specific layer(s). See Layer Targeting.
  • remove() - remove the menu from the map.

Events:

show

Fired when the context menu is displayed.

Type: ContextMenuEvent

menu.on("show", (e) => {
  console.log(`Menu opened at ${e.lngLat.lng}, ${e.lngLat.lat}`);
});

hide

Fired when the context menu is closed.

Type: ContextMenuEvent

menu.on("hide", (e) => {
  console.log("Menu closed");
});

ContextMenuItem

A clickable menu item with optional content slots.

const item = new ContextMenuItem({
  label: "Copy coordinates",
  start: { className: "fa-solid fa-copy" }
});

item.on("click", ({ lngLat, map, point, features }) => {
  // Handle click
});

Options:

  • label - a text label to display.
  • start - content to display before the label. See Slot Content.
  • end - content to display after the label. See Slot Content.
  • disabled - whether the item is disabled. Defaults to false.
  • className - custom CSS class for the <li> element.
  • buttonClassName - custom CSS class for the <button> element.

Properties:

  • label - get/set the label text.
  • start - get/set the start slot content.
  • end - get/set the end slot content.
  • disabled - get/set the disabled state.

Events:

click

Fired when the menu item is clicked.

Type: ContextMenuItemEvent

item.on("click", (e) => {
  console.log(`Clicked at ${e.lngLat.lng}, ${e.lngLat.lat}`);
});

ContextMenuSubmenu

A menu item that displays a nested submenu on hover or click.

const submenu = new ContextMenuSubmenu({
  label: "More options",
  start: { className: "fa-solid fa-ellipsis" }
});

submenu.addItem(new ContextMenuItem({ label: "Option A" }));
submenu.addItem(new ContextMenuItem({ label: "Option B" }));

Options:

  • All ContextMenuItem options, plus:
  • showDelay - delay in ms before showing the submenu on hover. Defaults to 300.
  • hideDelay - delay in ms before hiding the submenu when mouse leaves. Defaults to 200.

Methods:

  • addItem(item) - add an item to the submenu.
  • insertItem(index, item) - insert an item at a specific index.
  • removeItem(item) - remove an item from the submenu.

ContextMenuLabel

A non-interactive text label for grouping menu items into sections.

menu.addItem(new ContextMenuLabel({ text: "Navigation" }));
menu.addItem(new ContextMenuItem({ label: "Center map here" }));
menu.addItem(new ContextMenuItem({ label: "Zoom in" }));

Options:

  • text - the text to display.
  • className - custom CSS class for the label element.

ContextMenuSeparator

A horizontal line for visually grouping menu items.

menu.addItem(new ContextMenuItem({ label: "Edit" }));
menu.addItem(new ContextMenuSeparator());
menu.addItem(new ContextMenuItem({ label: "Delete" }));

Options:

  • className - custom CSS class for the separator element.

ContextMenuEvent

Fired by MapboxContextMenu.

| Property | Type | Description | |----------|------|-------------| | type | "show" | "hide" | The event type. | | target | MapboxContextMenu | The context menu that fired the event. | | map | Map | The Mapbox GL or MapLibre GL map instance. | | lngLat | { lng: number, lat: number } | Geographic coordinates of the original right-click. | | point | { x: number, y: number } | Pixel coordinates relative to the map container. | | features | Feature[] | Features at the click location (when menu is layer-scoped). | | originalEvent | MouseEvent | The original DOM event. |

ContextMenuItemEvent

Fired by ContextMenuItem.

| Property | Type | Description | |----------|------|-------------| | type | "click" | The event type. | | target | ContextMenuItem | The menu item that fired the event. | | map | Map | The Mapbox GL or MapLibre GL map instance. | | lngLat | { lng: number, lat: number } | Geographic coordinates of the original right-click. | | point | { x: number, y: number } | Pixel coordinates relative to the map container. | | features | Feature[] | Features at the click location (when menu is layer-scoped). | | originalEvent | MouseEvent | The original DOM click event. |

Slots

The start and end slots accept three types of content:

String

Rendered as text content:

new ContextMenuItem({
  label: "Rating",
  end: "★★★"
});

HTMLElement

For full control, pass a DOM element directly:

const icon = document.createElement("i");
icon.className = "fa-solid fa-star";

new ContextMenuItem({
  label: "Favorite",
  start: icon
});

Object Notation

Create elements declaratively:

new ContextMenuItem({
  label: "Favorite",
  start: { className: "fa-solid fa-star" }
});

Object notation supports:

  • as - element type to create. Defaults to 'span'.
  • className - CSS class name(s) to apply.
  • content - text content for the element.
  • onClick - click event handler.
new ContextMenuItem({
  label: "Settings",
  start: { as: "i", className: "fa-solid fa-gear" },
  end: { content: "Beta", className: "badge" }
});

Layer Targeting

Context menus can be scoped to specific map layers, so they only appear when the contextmenu event is triggered on features in those layers.

Pass a layer ID or array of layer IDs to addTo():

// Single layer
menu.addTo(map, "building");

// Multiple layers
menu.addTo(map, ["building", "building-outline"]);

When the menu is triggered, the features property in the click event will contain one or more features at that location:

item.on("click", ({ features }) => {
  if (features && features.length > 0) {
    console.log(features[0].properties);
  }
});

Featureset Targeting (Mapbox GL JS v3.9.0+)

Mapbox GL JS v3.9.0 introduced expanded targeting options, through the Interactions API, that allow you to target featuresets in imported basemaps like Mapbox Standard:

menu.addTo(map, { featuresetId: "buildings", importId: "basemap" });

You can also target layers using this notation:

menu.addTo(map, { layerId: "my-custom-layer" });

The library automatically detects whether these options are available and falls back to the traditional layer-based approach for older versions or MapLibre GL JS.

Keyboard Navigation

The menu supports full keyboard navigation:

  • Arrow down/up - move focus between items
  • Arrow right - open a submenu when the submenu item is focused
  • Arrow left - close submenu and return to parent
  • Enter/space - activate the focused item
  • Escape - close the menu

Theming

The menu supports light and dark themes via the theme option. Use 'auto' to follow the user's system preference.

Custom styling can be applied via the className options on each component, or by overriding the CSS custom properties:

| Variable | Description | Light Default | Dark Default | | -------------------------------------- | ----------------------- | ------------- | ------------ | | --context-menu-bg | Menu background color | white | #141414 | | --context-menu-font-family | Menu font family | Inherited from map | Inherited from map | | --context-menu-border-radius | Menu border radius | 5px | 5px | | --context-menu-min-width | Menu minimum width | 200px | 200px | | --context-menu-item-text-color | Item text color | black | white | | --context-menu-item-font-size | Item font size | 13px | 13px | | --context-menu-item-focus-bg | Focused item background | #e8e8e8 | #444444 | | --context-menu-item-active-bg | Active item background | #f3f3f3 | #2a2a2a | | --context-menu-item-disabled-opacity | Disabled item opacity | 0.5 | 0.5 | | --context-menu-button-height | Button height | 30px | 30px | | --context-menu-button-radius | Button border radius | 2.5px | 2.5px | | --context-menu-separator-color | Separator line color | #e8e8e8 | #505050 |

License

MIT