ActionMenu
Dropdown menu for contextual actions, commonly used in table rows for row-level operations.
Overview
The ActionMenu component provides a dropdown menu for contextual actions. It's commonly used in table rows, cards, and other contexts where multiple actions need to be accessible without cluttering the UI. Supports keyboard navigation, item variants, and dividers for grouping actions.
import { ActionMenu, IconButton } from '@enara-health/ui-react';
import { MoreVertical, Eye, Edit, Trash } from 'lucide-react';
<ActionMenu
trigger={<IconButton icon={<MoreVertical />} aria-label="Actions" />}
items={[
{ id: 'view', icon: <Eye />, label: 'View Details', onClick: handleView },
{ id: 'edit', icon: <Edit />, label: 'Edit', onClick: handleEdit },
{ divider: true },
{ id: 'delete', icon: <Trash />, label: 'Delete', onClick: handleDelete, variant: 'danger' },
]}
/> Note: ActionMenu is an interactive component. To see it in
action, run nx dev @enara-health/ui-react and view the component
in the dev preview.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
trigger | ReactNode | - | Required. Element that triggers the menu (typically IconButton) |
items | ActionMenuItemOrDivider[] | - | Required. Array of menu items and dividers |
position | 'auto' | 'top' | 'bottom' | 'auto' | Preferred vertical position of the dropdown |
align | 'start' | 'end' | 'end' | Horizontal alignment relative to trigger |
ActionMenuItem
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier for the item |
label | string | Text label for the item |
icon | ReactNode | Icon displayed before the label |
onClick | () => void | Click handler for the item |
variant | 'default' | 'danger' | 'success' | Visual variant for semantic meaning |
disabled | boolean | Whether the item is disabled |
ActionMenuDivider
To add a divider between items, include an object with divider: true in the items array.
Variants
Item Variants
Menu items support visual variants for semantic actions:
// Default variant (neutral)
{ id: 'edit', label: 'Edit', onClick: handleEdit }
// Danger variant for destructive actions
{ id: 'delete', label: 'Delete', onClick: handleDelete, variant: 'danger' }
// Success variant for positive actions
{ id: 'approve', label: 'Approve', onClick: handleApprove, variant: 'success' } Alignment
Control how the dropdown menu aligns relative to the trigger button:
align="start" align="end" default Examples
Table Row Actions
Common pattern for table row action menus with icons.
<ActionMenu
trigger={<IconButton icon={<MoreVertical />} aria-label="Row actions" />}
items={[
{ id: 'view', icon: <Eye />, label: 'View Profile', onClick: handleView },
{ id: 'edit', icon: <Edit />, label: 'Edit User', onClick: handleEdit },
{ divider: true },
{ id: 'delete', icon: <Trash />, label: 'Delete User', onClick: handleDelete, variant: 'danger' },
]}
/> Card Options
Options menu for card-based content.
<ActionMenu
trigger={<IconButton icon={<MoreVertical />} size="sm" aria-label="Options" />}
items={[
{ id: 'share', icon: <Share />, label: 'Share', onClick: handleShare },
{ id: 'duplicate', icon: <Copy />, label: 'Duplicate', onClick: handleDuplicate },
{ id: 'archive', icon: <Archive />, label: 'Archive', onClick: handleArchive },
]}
align="end"
/> With Dividers
Group related actions with dividers for better organization.
items={[
// Primary actions
{ id: 'view', label: 'View', onClick: handleView },
{ id: 'edit', label: 'Edit', onClick: handleEdit },
{ divider: true },
// Secondary actions
{ id: 'duplicate', label: 'Duplicate', onClick: handleDuplicate },
{ id: 'archive', label: 'Archive', onClick: handleArchive },
{ divider: true },
// Destructive action (always last)
{ id: 'delete', label: 'Delete', onClick: handleDelete, variant: 'danger' },
]} Disabled Items
Items can be disabled when actions aren't currently available.
items={[
{ id: 'view', label: 'View', onClick: handleView },
{ id: 'edit', label: 'Edit', onClick: handleEdit, disabled: true },
{ id: 'delete', label: 'Delete', onClick: handleDelete, disabled: true, variant: 'danger' },
]} Approval Workflow
Using success and danger variants for approval actions.
<ActionMenu
trigger={<IconButton icon={<MoreHorizontal />} aria-label="Review actions" />}
items={[
{ id: 'approve', icon: <Check />, label: 'Approve', onClick: handleApprove, variant: 'success' },
{ id: 'reject', icon: <X />, label: 'Reject', onClick: handleReject, variant: 'danger' },
{ divider: true },
{ id: 'comment', icon: <MessageSquare />, label: 'Add Comment', onClick: handleComment },
]}
/> Accessibility
- Role: Menu uses
role="menu"with items usingrole="menuitem". - Keyboard Navigation: Arrow Up/Down to navigate, Enter/Space to select, Escape to close, Home/End for first/last item.
- Focus Management: Focus is trapped in the menu when open and returns to trigger on close.
- ARIA Attributes: Trigger has
aria-haspopup="menu"andaria-expanded. - WCAG Compliance: Meets AA standards for interactive menus.
Best Practices
- Use IconButton with aria-label for icon-only triggers
- Keep primary actions visible - use menus for secondary actions
- Group related actions with dividers
- Use danger variant for destructive actions like delete
- Place destructive actions at the bottom, separated by a divider
- Limit menu items to 7 or fewer - consider alternative UI for many actions
- Provide clear, concise labels for each action