Skip to main content

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
navId
string | RegExp
required
Discord’s internal navId used to identify context menus. Can be a string, glob pattern (with *), or RegExp.
callback
function
required
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
navId
string | RegExp
required
The original navId from patching
callback
function
required
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
props.type
string
default:"text"
Type of menu item: "text", "submenu", "toggle", "radio", "custom", or "separator"
props.label
string
Display text for the menu item
props.id
string
Unique identifier. Auto-generated from label if not provided.
props.action
function
Function to call when item is clicked
props.disabled
boolean
default:"false"
Whether the item is disabled
props.danger
boolean
default:"false"
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
  }
});

buildMenuChildren

Creates all items and groups of a context menu recursively.
BdApi.ContextMenu.buildMenuChildren(
  setup: Array<MenuItemProps | MenuGroupProps>
): React.ReactElement[]
setup
array
required
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")
      }
    ]
  }
]);

buildMenu

Creates a complete context menu component including the wrapping container.
BdApi.ContextMenu.buildMenu(
  setup: Array<MenuItemProps | MenuGroupProps>
): React.ComponentType
setup
array
required
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
event
MouseEvent
required
The context menu event. This provides the position and target for the menu.
menuComponent
React.ComponentType
required
Component to render. Can be any React component or output of buildMenu().
config.position
string
default:"right"
Default position for the menu: "left" or "right"
config.align
string
default:"top"
Default alignment for the menu: "top" or "bottom"
config.onClose
function
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.
BdApi.ContextMenu.Menu

Item

Standard menu item component.
BdApi.ContextMenu.Item

Group

Menu group component for separating items.
BdApi.ContextMenu.Group

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

Adding an item to the user context menu

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?.();
  }
};

Creating a custom context menu

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);
    });
  }
};

Adding a submenu with multiple options

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);
});