Documentation Index
Fetch the complete documentation index at: https://mintlify.com/betterdiscord/betterdiscord/llms.txt
Use this file to discover all available pages before exploring further.
BdApi.ContextMenu provides utilities for patching Discord’s context menus and building custom menu items.
Methods
patch
Patches a given context menu to add custom items or modify existing ones.
BdApi.ContextMenu.patch(
navId: string | RegExp,
callback: (tree: React.ReactElement, props: MenuProps) => void
): () => void
Discord’s internal navId used to identify context menus. Can be a string, glob pattern (with *), or RegExp.
Callback function that receives the React render tree and props. Modify the tree to add/remove items.
Returns a function that automatically unpatches when called.
// Patch user context menu
const unpatch = BdApi.ContextMenu.patch("user-context", (tree, props) => {
const newItem = BdApi.ContextMenu.buildItem({
label: "Custom Action",
action: () => console.log("Clicked!", props.user)
});
tree.props.children.push(newItem);
});
// Later: remove the patch
unpatch();
Common navIds
"user-context" - User right-click menu
"message-context" - Message right-click menu
"channel-context" - Channel right-click menu
"guild-context" - Server right-click menu
"gdm-context" - Group DM context menu
Using patterns
// Glob pattern - matches channel-context, user-context, etc.
BdApi.ContextMenu.patch("*-context", (tree, props) => {
// Add to all context menus
});
// RegExp pattern
BdApi.ContextMenu.patch(/^(user|member)-context$/, (tree, props) => {
// Add to user and member context menus only
});
unpatch
Manually removes a patch from a context menu.
BdApi.ContextMenu.unpatch(
navId: string | RegExp,
callback: Function
): void
The original navId from patching
The original callback function from patching
const myCallback = (tree, props) => {
// ...
};
BdApi.ContextMenu.patch("user-context", myCallback);
// Later: unpatch manually
BdApi.ContextMenu.unpatch("user-context", myCallback);
buildItem
Builds a single context menu item.
BdApi.ContextMenu.buildItem(props: {
type?: "text" | "submenu" | "toggle" | "radio" | "custom" | "separator",
label?: string,
id?: string,
action?: (event: MouseEvent) => void,
disabled?: boolean,
danger?: boolean,
// ... and more based on type
}): React.ReactElement
Type of menu item: "text", "submenu", "toggle", "radio", "custom", or "separator"
Display text for the menu item
Unique identifier. Auto-generated from label if not provided.
Function to call when item is clicked
Whether the item is disabled
Whether to style the item as dangerous (red text)
Basic item
const item = BdApi.ContextMenu.buildItem({
label: "Copy ID",
action: () => {
BdApi.UI.showToast("ID copied!");
}
});
Toggle item
const toggleItem = BdApi.ContextMenu.buildItem({
type: "toggle",
label: "Enable Feature",
checked: false,
action: (event) => {
console.log("New state:", event.target.checked);
}
});
const submenu = BdApi.ContextMenu.buildItem({
type: "submenu",
label: "More Actions",
items: [
{
label: "Action 1",
action: () => console.log("Action 1")
},
{
label: "Action 2",
action: () => console.log("Action 2")
}
]
});
Separator
const separator = BdApi.ContextMenu.buildItem({
type: "separator"
});
Danger item
const dangerItem = BdApi.ContextMenu.buildItem({
label: "Delete",
danger: true,
action: () => {
// Perform deletion
}
});
Creates all items and groups of a context menu recursively.
BdApi.ContextMenu.buildMenuChildren(
setup: Array<MenuItemProps | MenuGroupProps>
): React.ReactElement[]
Array of item props used to build items. See buildItem for item props.
const children = BdApi.ContextMenu.buildMenuChildren([
{
type: "group",
items: [
{
label: "Item 1",
action: () => console.log(1)
},
{
label: "Item 2",
action: () => console.log(2)
}
]
},
{
type: "group",
items: [
{
type: "toggle",
label: "Toggle Item",
checked: true,
action: (e) => console.log("Toggled")
}
]
}
]);
Creates a complete context menu component including the wrapping container.
BdApi.ContextMenu.buildMenu(
setup: Array<MenuItemProps | MenuGroupProps>
): React.ComponentType
Array of item props used to build items. See buildMenuChildren.
Returns a React component that can be used with open().
const myMenu = BdApi.ContextMenu.buildMenu([
{
label: "Option 1",
action: () => console.log("Option 1")
},
{
type: "separator"
},
{
label: "Option 2",
action: () => console.log("Option 2")
}
]);
// Use with open()
document.addEventListener('contextmenu', (event) => {
BdApi.ContextMenu.open(event, myMenu);
});
open
Opens a context menu at the mouse position.
BdApi.ContextMenu.open(
event: MouseEvent,
menuComponent: React.ComponentType,
config?: {
position?: "left" | "right",
align?: "top" | "bottom",
onClose?: () => void
}
): void
The context menu event. This provides the position and target for the menu.
Component to render. Can be any React component or output of buildMenu().
Default position for the menu: "left" or "right"
Default alignment for the menu: "top" or "bottom"
Function to run when the menu is closed
const menu = BdApi.ContextMenu.buildMenu([
{label: "Copy", action: () => {}},
{label: "Paste", action: () => {}}
]);
document.querySelector('.my-element').addEventListener('contextmenu', (e) => {
e.preventDefault();
BdApi.ContextMenu.open(e, menu, {
position: "left",
onClose: () => console.log("Menu closed")
});
});
close
Closes the currently opened context menu immediately.
BdApi.ContextMenu.close(): void
BdApi.ContextMenu.close();
Components
Direct access to Discord’s context menu components for advanced usage.
The main menu container component.
Item
Standard menu item component.
Group
Menu group component for separating items.
Separator
Menu separator component.
BdApi.ContextMenu.Separator
CheckboxItem
Toggle/checkbox menu item component.
BdApi.ContextMenu.CheckboxItem
RadioItem
Radio button menu item component.
BdApi.ContextMenu.RadioItem
ControlItem
Control menu item component.
BdApi.ContextMenu.ControlItem
Usage examples
module.exports = class MyPlugin {
start() {
this.unpatchUser = BdApi.ContextMenu.patch("user-context", (tree, props) => {
const item = BdApi.ContextMenu.buildItem({
label: "Copy User ID",
action: () => {
DesktopAPI.clipboard.copy(props.user.id);
BdApi.UI.showToast("ID copied!", {type: "success"});
}
});
tree.props.children.push(item);
});
}
stop() {
this.unpatchUser?.();
}
};
module.exports = class MyPlugin {
start() {
const menu = BdApi.ContextMenu.buildMenu([
{
type: "group",
items: [
{
label: "Action 1",
action: () => console.log("Action 1")
},
{
label: "Action 2",
action: () => console.log("Action 2")
}
]
},
{
type: "group",
items: [
{
type: "toggle",
label: "Enable Feature",
checked: this.settings.enabled,
action: () => {
this.settings.enabled = !this.settings.enabled;
this.saveSettings();
}
}
]
}
]);
document.querySelector('#my-button').addEventListener('contextmenu', (e) => {
e.preventDefault();
BdApi.ContextMenu.open(e, menu);
});
}
};
BdApi.ContextMenu.patch("message-context", (tree, props) => {
const submenu = BdApi.ContextMenu.buildItem({
type: "submenu",
label: "My Plugin",
items: [
{
label: "Option 1",
action: () => console.log("Option 1", props.message)
},
{
label: "Option 2",
action: () => console.log("Option 2", props.message)
},
{
type: "separator"
},
{
label: "Delete",
danger: true,
action: () => console.log("Delete", props.message)
}
]
});
tree.props.children.push(submenu);
});