Skip to main content
The MenuItem component represents an actionable item within a menu or list. It supports icons, custom content slots, and various states like selected and highlighted.

Basic Usage

import { MenuItem } from 'reshaped';

function App() {
  return (
    <MenuItem onClick={() => console.log('Clicked')}>
      Menu Item
    </MenuItem>
  );
}

With Icons

Add an icon to the start of the menu item:
import { MenuItem } from 'reshaped';
import IconHome from '@/icons/Home';
import IconSettings from '@/icons/Settings';
import IconUser from '@/icons/User';

<MenuItem icon={IconHome} onClick={() => navigate('/')}>
  Home
</MenuItem>
<MenuItem icon={IconUser} onClick={() => navigate('/profile')}>
  Profile
</MenuItem>
<MenuItem icon={IconSettings} onClick={() => navigate('/settings')}>
  Settings
</MenuItem>

Sizes

MenuItem supports three size options:
<MenuItem size="small">Small Item</MenuItem>
<MenuItem size="medium">Medium Item</MenuItem>
<MenuItem size="large">Large Item</MenuItem>

Colors

MenuItem can be displayed in multiple colors:
<MenuItem color="neutral">Neutral Item</MenuItem>
<MenuItem color="primary">Primary Item</MenuItem>
<MenuItem color="critical">Delete Item</MenuItem>

States

Selected State

Highlight a menu item as selected:
<MenuItem selected>
  Selected Item
</MenuItem>

Highlighted State

Highlight a menu item (e.g., for keyboard navigation):
<MenuItem highlighted>
  Highlighted Item
</MenuItem>

Disabled State

Disable user interaction:
<MenuItem disabled>
  Disabled Item
</MenuItem>

Custom Slots

Use start and end slots for custom content:
import { MenuItem, Badge, Switch } from 'reshaped';

<MenuItem
  startSlot={<Avatar src="/avatar.jpg" size="small" />}
  endSlot={<Badge>New</Badge>}
>
  User Profile
</MenuItem>

<MenuItem
  endSlot={<Switch checked />}
>
  Enable notifications
</MenuItem>
Use MenuItem for navigation:
<MenuItem href="/dashboard">
  Dashboard
</MenuItem>

Rounded Corners

Apply rounded corners to the menu item:
<MenuItem roundedCorners>
  Rounded Item
</MenuItem>
Align menu items within a container:
import { MenuItem } from 'reshaped';

function App() {
  return (
    <MenuItem.Aligner side="inline">
      <MenuItem>Aligned Item</MenuItem>
    </MenuItem.Aligner>
  );
}

Basic Menu

import { MenuItem, View } from 'reshaped';
import IconEdit from '@/icons/Edit';
import IconCopy from '@/icons/Copy';
import IconTrash from '@/icons/Trash';

function ContextMenu() {
  return (
    <View gap={1} padding={2} backgroundColor="elevated">
      <MenuItem icon={IconEdit} onClick={handleEdit}>
        Edit
      </MenuItem>
      <MenuItem icon={IconCopy} onClick={handleCopy}>
        Duplicate
      </MenuItem>
      <MenuItem icon={IconTrash} color="critical" onClick={handleDelete}>
        Delete
      </MenuItem>
    </View>
  );
}
import { MenuItem, View } from 'reshaped';
import IconHome from '@/icons/Home';
import IconUser from '@/icons/User';
import IconSettings from '@/icons/Settings';

function NavigationMenu({ activePath }) {
  return (
    <View gap={1}>
      <MenuItem
        icon={IconHome}
        href="/"
        selected={activePath === '/'}
      >
        Home
      </MenuItem>
      <MenuItem
        icon={IconUser}
        href="/profile"
        selected={activePath === '/profile'}
      >
        Profile
      </MenuItem>
      <MenuItem
        icon={IconSettings}
        href="/settings"
        selected={activePath === '/settings'}
      >
        Settings
      </MenuItem>
    </View>
  );
}

Keyboard Navigation

function KeyboardMenu() {
  const [highlightedIndex, setHighlightedIndex] = useState(0);
  const items = ['Item 1', 'Item 2', 'Item 3'];
  
  return (
    <View gap={1}>
      {items.map((item, index) => (
        <MenuItem
          key={index}
          highlighted={highlightedIndex === index}
          onClick={() => handleSelect(item)}
        >
          {item}
        </MenuItem>
      ))}
    </View>
  );
}

Props

color
'neutral' | 'critical' | 'primary'
default:"primary"
Component color based on color tokens
size
'small' | 'medium' | 'large'
default:"medium"
Component size (responsive)
icon
React.ComponentType
SVG component for the icon at the start position
startSlot
React.ReactNode
Node for inserting custom content at the start side of the component
endSlot
React.ReactNode
Node for inserting custom content at the end side of the component
selected
boolean
default:"false"
Highlight the component as selected
highlighted
boolean
default:"false"
Highlight the component as hovered or focused (e.g., for keyboard navigation)
disabled
boolean
default:"false"
Disable user interaction
roundedCorners
boolean
default:"false"
Round the corners of the component (responsive)
href
string
URL to navigate to when clicked
onClick
(event: React.MouseEvent) => void
Callback when the item is clicked
stopPropagation
boolean
Stop event propagation when clicked
as
React.ElementType
Override the root element type
render
function
Custom render function for advanced use cases
className
string
Additional CSS class name
attributes
object
Additional HTML attributes
children
React.ReactNode
required
Item content
side
'start' | 'end' | 'inline'
default:"inline"
Side to align the menu item to
children
React.ReactElement
required
MenuItem element to align
className
string
Additional CSS class name
attributes
object
Additional HTML attributes

Build docs developers (and LLMs) love