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

@alekstar79/context-menu

v2.1.3

Published

Context Menu TS is a customizable radial context menu for web applications, written in TypeScript.

Readme

Context Menu TS (Vanilla/Vue3)

NPM Version License GitHub TypeScript Coverage

A beautiful and customizable radial context menu written in TypeScript. It can be used both as a plain JavaScript/TypeScript module and as a Vue component. The project includes full TypeScript support (types are exported) and provides a simple API for controlling the menu (show/hide, event subscription). The library is lightweight, has no required dependencies (Vue 3 is optional), and can be easily integrated into existing projects.

slider

View Live Demo

✨ Features

🎨 Customizable appearance (colors, radii, opacity)
🖼️ SVG icon support via sprites
💬 Hints with optional background
🖱️ Hover and wheel animations
🧩 Optional central button
📦 Two usage modes: vanilla JS and Vue 3 component
⚡ Full TypeScript support (types included)

📦 Installation

npm install @alekstar79/context-menu

The library has an optional peer dependency on vue. If you are using the Vue component, install Vue 3 as well:

npm install vue@^3

🚀 Usage

  1. Vanilla JS / TypeScript
import { defineConfig, Manager } from '@alekstar79/context-menu'

const config = defineConfig({
  sprite: '/path/to/icons.svg',  // path to SVG sprite
  innerRadius: 50,
  outerRadius: 150,
  opacity: 0.7,
  color: '#1976D2',
  sectors: [
    { icon: 'new', hint: 'New' },
    { icon: 'open', hint: 'Open' },
    { icon: 'save', hint: 'Save' }
  ],
  centralButton: {
    icon: 'home',
    hint: 'Home',
    hintPosition: 'top'
  }
})

// container element where the menu will be placed
const container = document.getElementById('menu-container')
const menu = new Manager(container, config)

// subscribe to events
menu.on('click', (data) => {
  console.log(`Selected: ${data.hint}`)
})

// show menu at cursor position (e.g., on contextmenu)
window.addEventListener('contextmenu', (e) => {
  e.preventDefault()
  menu.show(e)
})
  1. Vue Component
<template>
  <CircularMenu
    ref="menuRef"
    :sprite="sprite"
    :inner-radius="75"
    :outer-radius="150"
    :sectors="sectors"
    :central-button="centralButton"
    color="#42B883"
    @click="onMenuItemClick"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import type { ISector } from '@alekstar79/context-menu/context-menu'
import ContextMenu from '@alekstar79/context-menu/context-menu/vue'

const sprite = '/icons.svg'
const sectors: ISector[] = [
  { icon: 'new', hint: 'New' },
  { icon: 'open', hint: 'Open' },
  { icon: 'save', hint: 'Save' }
];

const centralButton = {
  icon: 'home',
  hint: 'Home',
  hintPosition: 'bottom'
}

const menuRef = ref()

const onMenuItemClick = (data: { icon: string; hint: string }) => {
  console.log('Selected:', data.hint)
}

// Example of manually showing the menu
const showMenu = (e: PointerEvent) => {
  menuRef.value?.show(e)
}
</script>

⚙️ Configuration

defineConfig(options: Partial<IConfig>): IConfig

Creates a configuration object with default values.

IConfig interface

| Property | Type | Default | Description | |---------------------|----------------|----------------|----------------------------------------------------------------------------------------------| | sprite | string | ../icons.svg | Path to the SVG sprite containing icons | | innerRadius | number | – | Inner radius of sectors (the smaller ring radius) | | outerRadius | number | – | Outer radius of sectors | | opacity | number | 0.7 | Opacity of sectors and hint backgrounds (if any) | | color | string | – | Main color for sectors and hint backgrounds (default '#1976D2' if omitted) | | hintPadding | number | – | Padding around the hint text (pixels). If not set, the hint is rendered without a background | | iconScale | number | – | Global scale factor for all icons (can be overridden per sector) | | iconRadius | number | – | Global radius at which icons are placed (can be overridden per sector) | | sectors | ISector[] | [] | Array of menu sectors | | centralButton | ICentralButton | – | Configuration for the central button | | autoBindContextMenu | boolean | true | Automatically bind the contextmenu event listener to window |

ISector interface

| Property | Type | Default | Description | |-------------|------------|---------|-------------------------------------------| | icon | string | – | Icon identifier (without #) | | hint | string | – | Hint text | | onclick | () => void | – | Click handler for the sector | | rotate | number | 0 | Additional rotation of the icon (degrees) | | iconScale | number | global | Icon scale for this specific sector | | iconRadius | number | global | Icon placement radius for this sector | | hintPadding | number | global | Hint padding for this sector |

ICentralButton interface

| Property | Type | Default | Description | |----------------|------------------|---------|-----------------------------------------------------------------| | icon | string | – | Icon identifier | | hint | string | – | Hint text | | onclick | () => void | – | Click handler | | iconScale | number | global | Icon scale | | iconRadius | number | global | Icon radius (effectively the button size) | | hintPosition | top \| bottom | top | Position of the hint relative to the button | | hintSpan | number | 180 | Angular span of the hint arc (degrees) | | hintDistance | number | 8 | Distance from button edge to the hint text (when no background) | | hintOffset | number | – | Absolute offset of the hint (overrides hintDistance) | | hintPadding | number | global | Hint padding for the central button | | hintStartAngle | number | – | Start angle of the arc (must be set together with hintEndAngle) | | hintEndAngle | number | – | End angle of the arc |

🧠 API

Manager class (vanilla)

const menu = new Manager(container: HTMLElement, config: IConfig)

Methods

  • show(event: MouseEvent | PointerEvent) – Shows the menu at the cursor position.
  • hide() – Hides the menu.
  • on(event: string, callback: Function) – Subscribes to events.

Events

  • click – Emitted when a sector or the central button is clicked. The callback receives { icon: string; hint: string }.

Vue component CircularMenu

Props

All properties from IConfig except sectors and centralButton (they are passed separately).
Additional props:

  • autoBindContextMenu – Automatically bind contextmenu to window (default true).

Events

  • click – Same as the vanilla click event.

Exposed methods (via ref)

  • show(event: PointerEvent) – Shows the menu.
  • hide() – Hides the menu.

💅 Styling

The library comes with basic styles that are automatically included. You can override them using the following CSS classes:

  • .context – Root menu container.
  • .radial-menu-svg – The SVG element.
  • .radial-sector – A sector.
  • .radial-icon – An icon.
  • .radial-hint – Hint text.
  • .radial-hint-bg – Hint background.
  • .central-sector, .central-icon, .central-hint – Central button elements.
  • .active – Class added to hints on hover.

Example of customization:

.radial-hint {
  font-size: 14px;
  font-weight: 600;
  fill: #000;
}

🛠️ Development

git clone <repo>
cd context-menu
npm install

Scripts

  • npm run dev – Start dev server with demo.
  • npm run build – Build the library.
  • npm run build:demo – Build the demo app.
  • npm run test – Run tests.
  • npm run test:ui – Run tests with UI.
  • npm run test:coverage – Run tests with coverage.

Project structure:

  • src/ – Source code.
  • src/menu/ – Core menu implementation.
  • src/components/ – Vue component.
  • src/core/ – Utilities and SVG wrapper.
  • public/ – Static assets for the demo.

📄 License

MIT © alekstar79

For more examples and a live demo, visit the repository. Feel free to open issues for questions or suggestions.