Skip to main content

ContextMenu

Right-click menu wrapper that resolves the clicked card and dispatches built-in actions. Wrap your <Kanban> in <ContextMenu> to get edit, duplicate, and delete on right-click with zero configuration. Extend it with custom entries and gate it per card.

The same menu instance also backs the per-card ... button when card.menu is enabled on <Kanban>.

Usage

import { ContextMenu } from "@svar-ui/vue-kanban";

Props

PropTypeDefaultDescription
apiKanbanInstanceApi | nullnullKanban instance for card lookup and action dispatch. Falls back to internal context if omitted.
optionsany[][]Menu items. Falls back to getMenuOptions() when empty.
resolver(card: KanbanCard, ev: MouseEvent) => any | nullnullGate called after card resolution. Return falsy to suppress the menu for that card.
filter(item: any, card: KanbanCard) => boolean | nullnullPer-item visibility filter. Return false to hide an item for the current card.
atstring"point"Menu placement mode.
onclick(e: any) => voidundefinedFires after built-in handling. Receives { action, context } where action.id is the item id.
cssstringundefinedExtra CSS class forwarded to the inner menu.

The wrapped content (typically <Kanban>) is passed via the default slot.

Methods

MethodSignatureDescription
showshow(ev: Event, obj?: any)Opens the menu programmatically. Use from a custom trigger button.

Built-in item IDs

IDTextDispatches
edit-cardEdit cardselect-card with card id
duplicate-cardDuplicate cardduplicate-card with card id
delete-cardDelete carddelete-card with card id

Custom item IDs don't auto-dispatch. Handle them in onclick.

Example

Default right-click menu:

<ContextMenu :api="api">
<Kanban ref="api" :cards="cards" :columns="columns" />
</ContextMenu>
<Editor v-if="api" :api="api" />

Extended menu with a custom action:

<script setup>
import { Kanban, ContextMenu, getMenuOptions } from "@svar-ui/vue-kanban";
import { ref } from "vue";

const api = ref(null);
const options = [
...getMenuOptions(),
{ id: "archive", text: "Archive", icon: "wxi-empty" },
];

function onclick({ action }) {
if (action.id === "archive") {
api.value.exec("update-card", {
id: action.context.id,
card: { archived: true },
});
}
}
</script>

<template>
<ContextMenu :api="api" :options="options" :onclick="onclick">
<Kanban ref="api" :cards="cards" :columns="columns" />
</ContextMenu>
</template>

Gated menu - block for read-only cards, hide delete for locked cards:

<template>
<ContextMenu
:api="api"
:resolver="(card) => !card.readOnly"
:filter="(item, card) => !(card.locked && item.id === 'delete-card')"
>
<Kanban ref="api" :cards="cards" :columns="columns" />
</ContextMenu>
</template>