syncfusion-react-context-menu — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited syncfusion-react-context-menu (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Complete API Reference & Feature Guide
ALWAYS use this skill when users need to:
📄 Read: references/getting-started.md
@syncfusion/ej2-react-navigations)The ContextMenuComponent accepts 18+ configuration properties to control behavior, appearance, and interaction:
#### target (Required) Type: string
CSS selector for the element that triggers the context menu (right-click or touch-hold).
<ContextMenuComponent target="#myElement" items={menuItems} />Example: Trigger on specific element
function App() {
return (
<div>
<div id="target">Right-click here</div>
<ContextMenuComponent target="#target" items={menuItems} />
</div>
);
}#### items (Required) Type: MenuItemModel[]
Array of menu items to display. Each item can have text, icons, nested items, separators, etc.
const menuItems: MenuItemModel[] = [
{ text: 'Cut' },
{ text: 'Copy' },
{ text: 'Paste' },
{ separator: true },
{
text: 'More',
items: [
{ text: 'Properties' },
{ text: 'Delete' }
]
}
];
<ContextMenuComponent target="#target" items={menuItems} />#### animationSettings Type: MenuAnimationSettingsModel
Configure menu opening/closing animation effects.
Properties:
effect: Animation type (None, SlideDown, ZoomIn, FadeIn)duration: Animation time in milliseconds (default: 400)easing: CSS easing function (default: ease)const animationSettings = {
effect: 'FadeIn',
duration: 300,
easing: 'ease-out'
};
<ContextMenuComponent
target="#target"
items={menuItems}
animationSettings={animationSettings}
/>Available Effects:
| Effect | Description |
|---|---|
None | No animation |
SlideDown | Slide down from top |
ZoomIn | Zoom in effect |
FadeIn | Fade in opacity |
#### cssClass Type: string
Add custom CSS classes to the ContextMenu wrapper for custom styling.
<ContextMenuComponent
target="#target"
items={menuItems}
cssClass="custom-menu dark-theme"
/>#### enableScrolling Type: boolean (default: false)
Enable scrolling when menu height exceeds available space.
<ContextMenuComponent
target="#target"
items={largeMenuList}
enableScrolling={true}
/>#### filter Type: string
CSS selector for specific elements inside the target that should trigger the context menu. Use to limit context menu to certain child elements.
// Context menu only appears on table rows, not the entire table
<ContextMenuComponent
target="#table"
filter="tr"
items={menuItems}
/>#### hoverDelay Type: number (default: 400)
Milliseconds to wait before displaying submenu on hover.
<ContextMenuComponent
target="#target"
items={menuItems}
hoverDelay={500} // 500ms before submenu appears
/>#### showItemOnClick Type: boolean (default: false)
Force submenus to open only on click (not on hover). When true, arrow key navigation is required to open submenus.
<ContextMenuComponent
target="#target"
items={menuItems}
showItemOnClick={true} // Submenus open on click only
/>#### itemTemplate Type: string | Function
Custom HTML template for menu items. Use template string with property placeholders (${propertyName}).
const template = `
<div class="menu-item">
<span class="${iconCss}"></span>
<span>${text}</span>
<span class="shortcut">${shortcut}</span>
</div>
`;
<ContextMenuComponent
target="#target"
items={menuItems}
itemTemplate={template}
/>#### locale Type: string (default: 'en-US')
Set localization language for component. Overrides global culture setting.
<ContextMenuComponent
target="#target"
items={menuItems}
locale="es-ES" // Spanish localization
/>#### enableHtmlSanitizer Type: boolean (default: true)
Enable HTML sanitization to prevent XSS attacks. Sanitizes untrusted HTML in menu items.
<ContextMenuComponent
target="#target"
items={menuItems}
enableHtmlSanitizer={true} // Sanitize HTML content
/>#### enablePersistence Type: boolean (default: false)
Persist component state (expanded/collapsed state) across page reloads using browser storage.
<ContextMenuComponent
target="#target"
items={menuItems}
enablePersistence={true}
/>#### enableRtl Type: boolean (default: false)
Enable right-to-left (RTL) layout for Arabic, Hebrew, and other RTL languages.
<ContextMenuComponent
target="#target"
items={menuItems}
enableRtl={true}
/>Each menu item is configured using MenuItemModel interface with the following properties:
#### text Type: string
Display text for the menu item.
{ text: 'Cut' }
{ text: 'Copy' }#### id Type: string
Unique identifier for the menu item. Use for identifying items in event handlers or programmatic operations.
{ id: 'cut-item', text: 'Cut' }
{ id: 'copy-item', text: 'Copy' }#### iconCss Type: string
CSS class for icon display. Supports Syncfusion icons or custom icon classes.
{ text: 'Cut', iconCss: 'e-icons e-cut' }
{ text: 'Copy', iconCss: 'e-icons e-copy' }
{ text: 'Delete', iconCss: 'e-icons e-delete' }#### items Type: MenuItemModel[]
Nested submenu items. Creates hierarchical menu structure.
{
text: 'File',
items: [
{ text: 'New' },
{ text: 'Open' },
{ text: 'Save' }
]
}#### separator Type: boolean (default: false)
Render as a visual separator line instead of a clickable item.
const menuItems: MenuItemModel[] = [
{ text: 'Cut' },
{ text: 'Copy' },
{ separator: true }, // Visual divider
{ text: 'Delete' }
];#### url Type: string
Navigation URL. Creates an anchor link that navigates when clicked.
{ text: 'Visit Site', url: 'https://example.com' }
{ text: 'Documentation', url: '/docs' }#### htmlAttributes Type: Record<string, string>
Add custom HTML attributes to menu item element.
{
text: 'Download',
htmlAttributes: {
'data-action': 'download',
'aria-label': 'Download file',
'title': 'Download the file'
}
}The ContextMenu exposes 15+ methods for runtime control and manipulation:
#### open(top: number, left: number, target?: HTMLElement): void
Programmatically open the context menu at specified coordinates.
Parameters:
top: Vertical position (Y-coordinate in pixels)left: Horizontal position (X-coordinate in pixels)target: Optional HTML element for z-index calculationfunction App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
const openMenuAtClick = (event: React.MouseEvent) => {
menuRef.current?.open(event.clientY, event.clientX);
};
return (
<div>
<button onClick={openMenuAtClick}>Open Menu</button>
<ContextMenuComponent ref={menuRef} target="#target" items={menuItems} />
</div>
);
}#### close(): void
Programmatically close the context menu.
function App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
const closeMenu = () => {
menuRef.current?.close();
};
const handleItemSelect = (args: MenuEventArgs) => {
console.log('Selected:', args.item?.text);
closeMenu(); // Close menu after selection
};
return (
<ContextMenuComponent
ref={menuRef}
target="#target"
items={menuItems}
select={handleItemSelect}
/>
);
}#### showItems(items: string[], isUniqueId?: boolean): void
Show menu items that were previously hidden.
Parameters:
items: Array of item text or IDs to showisUniqueId: If true, treat items as unique IDs; if false, treat as text (default: false)function App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
const showDeleteOption = () => {
menuRef.current?.showItems(['Delete', 'Rename']);
};
return (
<div>
<button onClick={showDeleteOption}>Show Options</button>
<ContextMenuComponent ref={menuRef} target="#target" items={menuItems} />
</div>
);
}#### hideItems(items: string[], isUniqueId?: boolean): void
Hide specific menu items from display while keeping them in the menu structure.
Parameters:
items: Array of item text or IDs to hideisUniqueId: If true, treat items as unique IDsfunction App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
React.useEffect(() => {
// Hide delete option for read-only mode
if (isReadOnly) {
menuRef.current?.hideItems(['Delete', 'Modify']);
}
}, [isReadOnly]);
return (
<ContextMenuComponent ref={menuRef} target="#target" items={menuItems} />
);
}#### enableItems(items: string[], enable: boolean, isUniqueId?: boolean): void
Enable or disable menu items to control interactivity.
Parameters:
items: Array of item text or IDs to modifyenable: true to enable, false to disableisUniqueId: If true, treat items as unique IDsfunction App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
const disablePasteIfNoClipboard = async () => {
const canPaste = await navigator.permissions.query({ name: 'clipboard-read' });
if (canPaste.state === 'denied') {
menuRef.current?.enableItems(['Paste'], false);
}
};
React.useEffect(() => {
disablePasteIfNoClipboard();
}, []);
return (
<ContextMenuComponent
ref={menuRef}
target="#target"
items={menuItems}
beforeOpen={disablePasteIfNoClipboard}
/>
);
}#### insertAfter(items: MenuItemModel[], text: string, isUniqueId?: boolean): void
Insert new menu items after a specified target item.
Parameters:
items: Array of new MenuItemModel items to inserttext: Text or ID of target item to insert afterisUniqueId: If true, treat text as unique IDfunction App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
const addSortByOption = () => {
const newItems: MenuItemModel[] = [
{ text: 'Sort By Name' },
{ text: 'Sort By Date' }
];
menuRef.current?.insertAfter(newItems, 'View');
};
return (
<div>
<button onClick={addSortByOption}>Add Sort Options</button>
<ContextMenuComponent ref={menuRef} target="#target" items={menuItems} />
</div>
);
}#### insertBefore(items: MenuItemModel[], text: string, isUniqueId?: boolean): void
Insert new menu items before a specified target item.
function App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
const addPremiumOptions = () => {
const premiumItems: MenuItemModel[] = [
{ text: 'Premium Feature 1' },
{ text: 'Premium Feature 2', iconCss: 'e-icons e-star' }
];
// Insert before 'Delete' option
menuRef.current?.insertBefore(premiumItems, 'Delete');
};
React.useEffect(() => {
if (user.isPremium) {
addPremiumOptions();
}
}, [user.isPremium]);
return (
<ContextMenuComponent ref={menuRef} target="#target" items={menuItems} />
);
}#### removeItems(items: string[], isUniqueId?: boolean): void
Remove menu items from the menu.
Parameters:
items: Array of item text or IDs to removeisUniqueId: If true, treat items as unique IDsfunction App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
const removeRestrictedActions = () => {
menuRef.current?.removeItems(['Delete', 'Export', 'Archive']);
};
React.useEffect(() => {
if (userRole === 'viewer') {
removeRestrictedActions();
}
}, [userRole]);
return (
<ContextMenuComponent
ref={menuRef}
target="#target"
items={menuItems}
created={removeRestrictedActions}
/>
);
}#### getItemIndex(item: MenuItem | string, isUniqueId?: boolean): number[]
Get the index/indices of a menu item. Returns array because item can exist at multiple levels (for nested items).
Parameters:
item: MenuItem object or text/ID string to findisUniqueId: If true, treat item as unique IDReturns: number[] - Array of index numbers representing item position
function App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
const findItemPosition = () => {
const indices = menuRef.current?.getItemIndex('Copy');
console.log('Copy is at index:', indices); // Output: [1] or [0, 1] for nested
const nestedIndices = menuRef.current?.getItemIndex('Open', false);
console.log('Open is at indices:', nestedIndices); // Output: [0, 1] for nested
};
return (
<div>
<button onClick={findItemPosition}>Find Item</button>
<ContextMenuComponent ref={menuRef} target="#target" items={menuItems} />
</div>
);
}#### setItem(item: MenuItem, id?: string, isUniqueId?: boolean): void
Update an existing menu item's properties.
Parameters:
item: MenuItem object with updated propertiesid: Text or ID of item to updateisUniqueId: If true, treat id as unique IDfunction App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
const updateDeleteItemStyle = () => {
const updatedItem: MenuItemModel = {
text: 'Delete',
iconCss: 'e-icons e-delete',
htmlAttributes: {
'class': 'dangerous-action'
}
};
menuRef.current?.setItem(updatedItem, 'Delete');
};
return (
<div>
<button onClick={updateDeleteItemStyle}>Update Delete Item</button>
<ContextMenuComponent ref={menuRef} target="#target" items={menuItems} />
</div>
);
}#### destroy(): void
Destroy the ContextMenu component and free resources.
function App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
React.useEffect(() => {
return () => {
// Cleanup on component unmount
menuRef.current?.destroy();
};
}, []);
return (
<ContextMenuComponent ref={menuRef} target="#target" items={menuItems} />
);
}The ContextMenu component provides 7 events for monitoring and controlling user interactions:
#### beforeOpen Type: EmitType<BeforeOpenCloseMenuEventArgs>
Fires before the menu opens. Use to prevent opening, modify items, or prepare data.
Event Arguments:
interface BeforeOpenCloseMenuEventArgs {
element: HTMLElement; // Menu element
event: Event; // Browser event object
items: MenuItemModel[]; // Current menu items
cancel: boolean; // Set to true to prevent action
parentItem?: MenuItemModel; // Parent item if submenu
}Example: Prevent opening in certain conditions
function App() {
const handleBeforeOpen = (args: BeforeOpenCloseMenuEventArgs) => {
// Prevent opening on read-only elements
const target = args.event?.target as HTMLElement;
if (target?.classList.contains('read-only')) {
args.cancel = true; // Prevent menu from opening
return;
}
// Modify items before opening
const selectedText = window.getSelection()?.toString();
if (!selectedText) {
// Disable text-related operations if no text selected
args.items = args.items?.map(item => ({
...item,
disabled: ['Copy', 'Cut'].includes(item.text as string)
}));
}
};
return (
<ContextMenuComponent
target="#target"
items={menuItems}
beforeOpen={handleBeforeOpen}
/>
);
}#### onOpen Type: EmitType<OpenCloseMenuEventArgs>
Fires after the menu opens. Use to initialize UI or perform post-open actions.
Event Arguments:
interface OpenCloseMenuEventArgs {
element: HTMLElement; // Menu element
event: Event; // Browser event that triggered opening
items: MenuItemModel[]; // Current menu items
}Example: Initialize after opening
function App() {
const handleOnOpen = (args: OpenCloseMenuEventArgs) => {
console.log('Menu opened at:', new Date());
console.log('Number of items:', args.items?.length);
// Set focus to first menu item for accessibility
setTimeout(() => {
const firstItem = args.element?.querySelector('.e-menu-item');
(firstItem as HTMLElement)?.focus();
}, 0);
};
return (
<ContextMenuComponent
target="#target"
items={menuItems}
onOpen={handleOnOpen}
/>
);
}#### beforeClose Type: EmitType<BeforeOpenCloseMenuEventArgs>
Fires before the menu closes. Use to prevent closing or save state.
Example: Prevent closing on unsaved changes
function App() {
const [hasUnsavedChanges, setHasUnsavedChanges] = React.useState(false);
const handleBeforeClose = (args: BeforeOpenCloseMenuEventArgs) => {
if (hasUnsavedChanges) {
const confirmed = window.confirm('Unsaved changes. Close anyway?');
if (!confirmed) {
args.cancel = true; // Prevent menu from closing
}
}
};
return (
<ContextMenuComponent
target="#target"
items={menuItems}
beforeClose={handleBeforeClose}
/>
);
}#### onClose Type: EmitType<OpenCloseMenuEventArgs>
Fires after the menu closes. Use for cleanup or state management.
Example: Clean up after menu closes
function App() {
const handleOnClose = (args: OpenCloseMenuEventArgs) => {
console.log('Menu closed');
// Clear temporary selections or states
document.querySelectorAll('.temp-highlight').forEach(el => {
el.classList.remove('temp-highlight');
});
};
return (
<ContextMenuComponent
target="#target"
items={menuItems}
onClose={handleOnClose}
/>
);
}#### select Type: EmitType<MenuEventArgs>
Fires when a menu item is clicked/selected. Use to execute actions based on selection.
Event Arguments:
interface MenuEventArgs {
element: HTMLElement; // Menu item element
event: Event; // Click/keyboard event
item?: MenuItemModel; // Selected menu item
items?: MenuItemModel[]; // All menu items
}Example: Execute actions on item selection
function App() {
const handleSelect = (args: MenuEventArgs) => {
const itemText = args.item?.text;
switch (itemText) {
case 'Cut':
document.execCommand('cut');
console.log('Cut executed');
break;
case 'Copy':
document.execCommand('copy');
console.log('Copy executed');
break;
case 'Paste':
document.execCommand('paste');
console.log('Paste executed');
break;
case 'Delete':
if (confirm('Confirm delete?')) {
console.log('Delete executed');
}
break;
}
};
return (
<ContextMenuComponent
target="#target"
items={menuItems}
select={handleSelect}
/>
);
}#### beforeItemRender Type: EmitType<MenuEventArgs>
Fires before each menu item renders. Use to customize item appearance or add custom logic.
Example: Conditionally disable items
function App() {
const handleBeforeItemRender = (args: MenuEventArgs) => {
const itemText = args.item?.text;
// Disable delete if user doesn't have permission
if (itemText === 'Delete' && !userPermissions.canDelete) {
args.element?.classList.add('e-disabled');
}
// Highlight recent items
if (itemText?.startsWith('Recent:')) {
args.element?.classList.add('recent-item-highlight');
}
// Add keyboard shortcut indicator
const shortcuts: Record<string, string> = {
'Cut': 'Ctrl+X',
'Copy': 'Ctrl+C',
'Paste': 'Ctrl+V'
};
if (shortcuts[itemText as string]) {
const shortcutEl = document.createElement('span');
shortcutEl.className = 'shortcut-hint';
shortcutEl.textContent = shortcuts[itemText as string];
args.element?.appendChild(shortcutEl);
}
};
return (
<ContextMenuComponent
target="#target"
items={menuItems}
beforeItemRender={handleBeforeItemRender}
/>
);
}#### created Type: EmitType<Event>
Fires after the component is fully created and rendered. Use for initialization.
Example: Initialize after creation
function App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
const handleCreated = () => {
console.log('ContextMenu created and ready');
// Perform initial setup
menuRef.current?.enableItems(['Advanced Options'], userRole === 'admin');
// Add custom data to items
const items = menuRef.current?.items;
if (items) {
items.forEach((item, index) => {
item.id = `item-${index}`;
});
}
};
return (
<ContextMenuComponent
ref={menuRef}
target="#target"
items={menuItems}
created={handleCreated}
/>
);
}📄 Read: references/menu-items-and-data-binding.md
📄 Read: references/templates-and-customization.md
📄 Read: references/styling-and-appearance.md
📄 Read: references/accessibility-and-keyboard-navigation.md
📄 Read: references/advanced-features.md
📄 Read: references/use-cases-and-patterns.md
import { ContextMenuComponent, MenuItemModel } from '@syncfusion/ej2-react-navigations';
import * as React from 'react';
function App() {
const menuRef = React.useRef<ContextMenuComponent>(null);
const menuItems: MenuItemModel[] = [
{ text: 'Cut', iconCss: 'e-icons e-cut', id: 'cut' },
{ text: 'Copy', iconCss: 'e-icons e-copy', id: 'copy' },
{ text: 'Paste', iconCss: 'e-icons e-paste', id: 'paste' },
{ separator: true },
{
text: 'More',
items: [
{ text: 'Delete' },
{ text: 'Properties' }
]
}
];
const handleSelect = (args: any) => {
console.log('Selected:', args.item?.text);
};
const handleBeforeOpen = (args: any) => {
// Customize menu before opening
};
return (
<div>
<div id="target">Right-click me</div>
<ContextMenuComponent
ref={menuRef}
target="#target"
items={menuItems}
select={handleSelect}
beforeOpen={handleBeforeOpen}
animationSettings={{ effect: 'FadeIn', duration: 300 }}
enableScrolling={true}
/>
</div>
);
}
export default App;// Open menu at coordinates
menuRef.current?.open(100, 150);
// Close menu
menuRef.current?.close();
// Enable/disable items
menuRef.current?.enableItems(['Delete', 'Archive'], false);
// Show/hide items
menuRef.current?.showItems(['Delete']);
menuRef.current?.hideItems(['Export']);
// Add items
menuRef.current?.insertAfter(
[{ text: 'New Option' }],
'Existing Item'
);
// Remove items
menuRef.current?.removeItems(['Outdated Item']);
// Get item index
const indices = menuRef.current?.getItemIndex('Copy');Next Steps: Choose reference based on your need. Start with getting-started.md, or explore specific features in other references.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.