Defines a custom action that appears in the context menu when elements are selected.
Properties
Unique identifier for this action. Used for deduplication and tracking.
Display text shown in the context menu.
Optional target specification. Use “context-menu” to explicitly mark this as a context menu action.
Keyboard shortcut hint displayed next to the action. Example: “⌘K” or “Ctrl+K”.
enabled
boolean | ((context: ActionContext) => boolean)
Whether this action is enabled. Can be a boolean or a function that receives the action context and returns a boolean. Disabled actions appear greyed out.
onAction
(context: ContextMenuActionContext) => void | Promise<void>
required
Called when the action is triggered. Receives the action context with element data and helper functions.
Optional agent configuration. When provided, this action can trigger AI-assisted operations. See AgentOptions.
Defines a custom action that appears in the toolbar dropdown menu.
Properties
Unique identifier for this action.
Display text shown in the toolbar menu.
Keyboard shortcut hint. Example: “⌘K” or “Ctrl+K”.
Must be “toolbar” to identify this as a toolbar action.
enabled
boolean | (() => boolean)
Whether this action is enabled. Can be a boolean or a function that returns a boolean.
Function that returns whether this action is currently active. Active actions are visually highlighted.
onAction
() => void | Promise<void>
required
Called when the action is triggered. No context is provided for toolbar actions.
ActionContext
Context object passed to action handlers with information about selected elements and helper functions.
Properties
The primary selected element. If multiple elements are selected, this is typically the first one.
Array of all selected elements.
File path where the element’s component is defined.
Line number where the element’s component is defined.
Name of the React component for this element.
HTML tag name of the element (lowercase).
enterPromptMode
(agent?: AgentOptions) => void
Function to enter prompt mode for AI-assisted operations. Optionally pass agent configuration.
hooks
ActionContextHooks
required
performWithFeedback
(action: () => Promise<boolean>) => Promise<void>
required
Execute an async action with visual feedback. Shows success/error flash based on return value.
- Return
true for success (shows success flash)
- Return
false for failure (shows error state)
- Throws errors are caught and shown as errors
Programmatically hide the context menu.
Clean up any temporary state or UI elements. Call before exiting action.
Extends ActionContext with additional context menu-specific functionality.
Properties
Inherits all properties from ActionContext plus:
Helper function to copy selected elements to clipboard using default behavior.
ActionContextHooks
Helper hooks provided in the action context for common operations.
Properties
transformHtmlContent
(html: string, elements: Element[]) => Promise<string>
required
Transform HTML content through all registered plugin transform hooks.
onOpenFile
(filePath: string, lineNumber?: number) => boolean | void
required
Trigger file opening with plugin hooks. Returns false if opening was prevented.
transformOpenFileUrl
(url: string, filePath: string, lineNumber?: number) => string
required
Transform file opening URL through all registered plugin hooks.
Usage
import { ContextMenuAction } from 'react-grab';
const logAction: ContextMenuAction = {
id: 'log-element',
label: 'Log to Console',
shortcut: '⌘L',
onAction: (context) => {
console.log('Selected element:', context.element);
console.log('Tag:', context.tagName);
console.log('Component:', context.componentName);
console.log('Total selected:', context.elements.length);
}
};
Conditional Action Enabling
const openFileAction: ContextMenuAction = {
id: 'open-file',
label: 'Open in Editor',
enabled: (context) => {
// Only enable if we have file location info
return !!context.filePath;
},
onAction: (context) => {
if (context.filePath) {
context.hooks.onOpenFile(context.filePath, context.lineNumber);
}
}
};
Action with Feedback
const saveAction: ContextMenuAction = {
id: 'save-snippet',
label: 'Save Snippet',
onAction: async (context) => {
await context.performWithFeedback(async () => {
const content = await getElementContent(context.element);
const success = await saveToDatabase(content);
return success; // true = success flash, false = error
});
context.cleanup();
}
};
Action with AI Agent
import { myAgent } from './agent';
const refactorAction: ContextMenuAction = {
id: 'refactor',
label: 'Refactor with AI',
agent: {
provider: myAgent,
onComplete: (session, elements) => {
console.log('Refactoring complete!');
}
},
onAction: (context) => {
// Automatically enters prompt mode with the configured agent
context.enterPromptMode?.();
}
};
import { ToolbarMenuAction } from 'react-grab';
let debugMode = false;
const toggleDebugAction: ToolbarMenuAction = {
id: 'toggle-debug',
label: 'Debug Mode',
target: 'toolbar',
shortcut: '⌘D',
isActive: () => debugMode,
onAction: () => {
debugMode = !debugMode;
console.log('Debug mode:', debugMode ? 'ON' : 'OFF');
}
};
Action with Copy Helper
const customCopyAction: ContextMenuAction = {
id: 'copy-with-metadata',
label: 'Copy with Metadata',
onAction: async (context) => {
// First use default copy
context.copy?.();
// Then add metadata to clipboard
const metadata = {
component: context.componentName,
file: context.filePath,
line: context.lineNumber,
count: context.elements.length
};
await navigator.clipboard.writeText(
JSON.stringify(metadata, null, 2)
);
}
};
const exportHtmlAction: ContextMenuAction = {
id: 'export-html',
label: 'Export HTML',
onAction: async (context) => {
await context.performWithFeedback(async () => {
const html = context.element.outerHTML;
// Transform through plugin hooks
const transformed = await context.hooks.transformHtmlContent(
html,
context.elements
);
// Save to file
const success = await downloadFile(
'export.html',
transformed
);
return success;
});
}
};
Registering Actions via Plugin
import { Plugin } from 'react-grab';
const myPlugin: Plugin = {
name: 'my-plugin',
actions: [
logAction,
openFileAction,
saveAction,
toggleDebugAction
]
};
// Register plugin to add actions
reactGrab.registerPlugin(myPlugin);
Type Definitions
export interface ContextMenuAction {
id: string;
label: string;
target?: 'context-menu';
shortcut?: string;
enabled?: boolean | ((context: ActionContext) => boolean);
onAction: (context: ContextMenuActionContext) => void | Promise<void>;
agent?: AgentOptions;
}
export interface ToolbarMenuAction {
id: string;
label: string;
shortcut?: string;
target: 'toolbar';
enabled?: boolean | (() => boolean);
isActive?: () => boolean;
onAction: () => void | Promise<void>;
}
export interface ActionContext {
element: Element;
elements: Element[];
filePath?: string;
lineNumber?: number;
componentName?: string;
tagName?: string;
enterPromptMode?: (agent?: AgentOptions) => void;
hooks: ActionContextHooks;
performWithFeedback: (action: () => Promise<boolean>) => Promise<void>;
hideContextMenu: () => void;
cleanup: () => void;
}
export interface ContextMenuActionContext extends ActionContext {
copy?: () => void;
}
export interface ActionContextHooks {
transformHtmlContent: (html: string, elements: Element[]) => Promise<string>;
onOpenFile: (filePath: string, lineNumber?: number) => boolean | void;
transformOpenFileUrl: (url: string, filePath: string, lineNumber?: number) => string;
}
See Also
- Plugin - Register actions via plugins
- Agent - Configure AI agents for actions