← Back to home

API Reference

context-menu-kit API

Reference for the shared core package, React components, Vue components, styling entry points, and customization hooks.

Packages

@context-menu-kit/core

Framework-agnostic state and event helpers. Use this package when you want to build your own renderer.

@context-menu-kit/react

React components and render props built on top of the core package.

@context-menu-kit/vue

Vue components and slots built on top of the core package.

pnpm add @context-menu-kit/core
pnpm add @context-menu-kit/core @context-menu-kit/react
pnpm add @context-menu-kit/core @context-menu-kit/vue

Core API

The core package stores the active context menu state and notifies subscribers whenever the menu opens or closes.

ContextMenuItem

type ContextMenuItem<T = unknown> = {
  id: string
  label?: string
  disabled?: boolean
  children?: ContextMenuItem<T>[]
  onClick?: (item: ContextMenuItem) => void
  data?: T
}
idRequired unique item id.
labelOptional text used by the default renderers.
disabledPrevents the default renderer from triggering the item.
childrenReserved for nested menu data.
onClickCalled when the user selects an enabled menu item.
dataCustom user data for renderers, slots, and app-specific logic.

openContextMenu(options)

import { openContextMenu } from '@context-menu-kit/core'

openContextMenu({
  id: 'file-menu',
  x: event.clientX,
  y: event.clientY,
  items,
  event,
  meta: {
    source: 'file-area',
  },
})

ContextMenuOpenOptions

type ContextMenuOpenOptions = {
  id: string
  x: number
  y: number
  items: ContextMenuItem[]
  meta?: Record<string, unknown>
  event?: MouseEvent
}

closeContextMenu()

import { closeContextMenu } from '@context-menu-kit/core'

closeContextMenu()

getContextMenuState()

import { getContextMenuState } from '@context-menu-kit/core'

const state = getContextMenuState()

subscribeContextMenu(listener)

import { subscribeContextMenu } from '@context-menu-kit/core'

const unsubscribe = subscribeContextMenu((state) => {
  console.log(state)
})

unsubscribe()

ContextMenuState

type ContextMenuState = {
  isOpen: boolean
  id: string | null
  x: number
  y: number
  items: ContextMenuItem[]
  event?: MouseEvent
  meta?: Record<string, unknown>
}

React API

The React package provides components and render props for common usage.

Imports

import {
  ContextMenu,
  ContextMenuProvider,
  closeContextMenu,
  type ContextMenuItem,
  type ContextMenuProps,
  type ContextMenuRenderOptions,
  type RenderItemProps,
  type RenderBodyProps,
} from '@context-menu-kit/react'

import '@context-menu-kit/react/styles.css'

<ContextMenuProvider>

Mount this once around the area that should support context menus. It automatically renders the global menu renderer.

<ContextMenuProvider>
  <App />
</ContextMenuProvider>

<ContextMenu>

type ContextMenuProps<T = unknown> = {
  items: ContextMenuItem<T>[]
  children: ReactNode
  bodyClass?: string
  itemClass?: string
  renderItem?: (props: RenderItemProps<T>) => ReactNode
  renderBody?: (props: RenderBodyProps<T>) => ReactNode
}

renderItem

<ContextMenu
  items={items}
  renderItem={({ item, close }) => (
    <button
      disabled={item.disabled}
      onClick={() => {
        if (item.disabled) return
        item.onClick?.(item)
        close()
      }}
    >
      {item.label}
    </button>
  )}
>
  <div>Right click here</div>
</ContextMenu>

renderBody

<ContextMenu
  items={items}
  renderBody={({ items, close }) => (
    <div className="my-menu">
      {items.map((item) => (
        <button
          key={item.id}
          disabled={item.disabled}
          onClick={() => {
            if (item.disabled) return
            item.onClick?.(item)
            close()
          }}
        >
          {item.label}
        </button>
      ))}
    </div>
  )}
>
  <div>Right click here</div>
</ContextMenu>

Vue API

The Vue package provides components and slots for common usage.

Imports

import {
  ContextMenu,
  ContextMenuProvider,
  closeContextMenu,
  type ContextMenuItem,
  type ContextMenuProps,
  type ContextMenuSlotProps,
  type ContextMenuBodySlotProps,
} from '@context-menu-kit/vue'

import '@context-menu-kit/vue/styles.css'

<ContextMenuProvider>

Mount this once around the area that should support context menus. It automatically renders the global menu renderer.

<ContextMenuProvider>
  <App />
</ContextMenuProvider>

<ContextMenu>

interface ContextMenuProps<T = unknown> {
  items: ContextMenuItem<T>[]
  bodyClass?: string
  itemClass?: string
}

#item slot

<ContextMenu :items="items">
  <template #item="{ item, close }">
    <button
      :disabled="item.disabled"
      type="button"
      @click="
        () => {
          if (item.disabled) return
          item.onClick?.(item)
          close()
        }
      "
    >
      {{ item.label }}
    </button>
  </template>

  <div>Right click here</div>
</ContextMenu>

#body slot

<ContextMenu :items="items">
  <template #body="{ items, close }">
    <div class="my-menu">
      <button
        v-for="item in items"
        :key="item.id"
        :disabled="item.disabled"
        type="button"
        @click="
          () => {
            if (item.disabled) return
            item.onClick?.(item)
            close()
          }
        "
      >
        {{ item.label }}
      </button>
    </div>
  </template>

  <div>Right click here</div>
</ContextMenu>

Styles

React and Vue packages both ship a default stylesheet. Import the stylesheet once in your app, or pass custom class names to replace the default body and item classes.

import '@context-menu-kit/react/styles.css'
import '@context-menu-kit/vue/styles.css'

Default classes

.cmk-body
.cmk-item
.cmk-item:hover
.cmk-item-disabled

Custom classes

<ContextMenu
  items={items}
  bodyClass="my-menu"
  itemClass="my-menu-item"
>
  <div>Right click here</div>
</ContextMenu>
<ContextMenu
  :items="items"
  body-class="my-menu"
  item-class="my-menu-item"
>
  <div>Right click here</div>
</ContextMenu>