Zetta v1.6

Components · Overlays & menus

Menu item

The rows inside a Menu or dropdown. Three types — a plain action (with optional icon, description and shortcut), a checkbox item for toggles, and a single-select item with a check for one-of-many. All hover and select in the Primary tint.

Preview

Actions
Show grid
Show rulers
Compact
Comfortable

Build with the skill

No package to install — hand this to your AI to generate or migrate the component in your stack.

Prompt for your AI
Apply the Zetta "Menu item" component to this project using the zetta-design-md skill.

WHEN TO USE
- Migrating or fixing existing code (the common case): audit the current implementation against the `menu-item` spec (variants: action, checkbox, single-select, danger) and CORRECT every deviation — replace off-spec values, don't only add new ones.
- New component: build it to the `menu-item` spec in this project's stack.

AUDIT & FIX (when the component already exists)
Compare it to the skill's spec and fix, don't just append: hardcoded colors/hex, off-scale radius, wrong fonts, dark/navy fills, shadows used in place of borders (or missing borders), brand lime used as a CTA or interaction (must be primary indigo), and any missing or wrong hover / focus / active / disabled / invalid state or missing 2px focus ring. Replace each with the correct Zetta token.

ALWAYS
- Pull the authoritative spec and tokens from the skill — never guess or hardcode values.
- Use this project's own component conventions and framework idioms.
- Honor the Zetta guardrails (brand = identity only, primary = interaction, shadows for overlays) and verify in Light, Dark, and Accessibility.

Anatomy & rules

╭─────────────────────────────────────────────╮
│ [icon]  Label text           ⌘K [shortcut] │  ← standard item
│         Optional description               │
├─────────────────────────────────────────────┤
│ [icon]  Danger action                      │  ← danger variant
╰─────────────────────────────────────────────╯

Parts:

  • dropdown-item-icon — optional leading icon (16px, {colors.muted})
  • dropdown-item-label — primary action text, truncated at container edge
  • dropdown-item-description — optional secondary line (12px muted)
  • dropdown-item-shortcut — optional trailing keyboard shortcut (11px muted, right-aligned)
  • dropdown-item-separator — 1px hairline divider between groups
  • dropdown-item-section-heading — optional group label above a section of items
State Background Text Icon
Rest transparent {colors.ink} {colors.muted}
Hover {colors.primary-bg} {colors.primary} {colors.primary}
Focus 2px inset {colors.border-focus}
Active {colors.primary-bg} {colors.primary}
Selected {colors.primary-bg} {colors.primary} / 500
Danger rest transparent {colors.danger} {colors.danger}
Danger hover {colors.danger-bg} {colors.danger}
Disabled transparent {colors.disabled-text}

When to use

  • Any menu action that triggers a single operation and should close the menu immediately.
  • Actions like: Edit, Duplicate, Rename, Export, Delete, Copy link, Move to, Open in new tab.

When not to use

Do

  • Use the danger variant only for irreversible or destructive actions. Position danger items last, separated by a dropdown-item-separator.
  • Show a shortcut only if the keyboard shortcut actually works — don't display decorative shortcuts.
  • Keep labels concise — verb + noun. "Delete item", "Copy link", "Move to project".

Don't

  • Don't use dropdown items as navigation links — use a Menu or Sidebar Nav for navigation.
  • Don't nest more than one level of sub-menus inside a dropdown.
  • Don't disable items without explaining why — use a tooltip on the trigger or add a description.
  • Labels: verb + noun phrase. "Delete project", "Export as CSV", "Copy shareable link".
  • Danger labels: be explicit — "Delete permanently", not just "Delete" if the action is irreversible.
  • Shortcuts: use standard OS notation. Mac: ⌘⇧K. Windows/Linux: Ctrl+Shift+K.
  • Description: one short phrase. Max 60 characters. Never required — use only when label alone is ambiguous.

Keyboard

Key Behavior
Tab Moves focus into and through menu items
Up / Down Arrow Navigate between items in the open dropdown
Home Move focus to first item
End Move focus to last item
Enter / Space Activate the focused item and close the menu
Escape Close the dropdown without activating an item

Accessibility

  • ARIA role: role="menuitem" on each item. role="menu" on the list container.
  • Disabled: aria-disabled="true". Do not use the disabled HTML attribute — it removes the item from focus order and keyboard focus, which breaks navigation.
  • Shortcut: use aria-keyshortcuts on the item to announce the keyboard shortcut to screen readers.
  • Danger: communicate destructive nature in the label text — don't rely on color alone.
  • Section heading: role="presentation" on headings — they are not interactive and should not be announced as actionable.

Spec

Values and token references resolved straight from the Zetta spec.

dropdown-item
display
flex
alignItems
center
gap
{spacing.sm}
paddingX
{spacing.sm}
paddingY
{spacing.xs}
borderRadius
{rounded.sm}
fontFamily
Geist
fontSize
14px
fontWeight
400
lineHeight
1.40
textColor
{colors.ink}
cursor
pointer
minHeight
32px
userSelect
none
dropdown-item-hover
backgroundColor
{colors.primary-bg}
textColor
{colors.primary}
dropdown-item-focus
outline
2px solid {colors.border-focus}
outlineOffset
-2px
dropdown-item-active
backgroundColor
{colors.primary-bg}
textColor
{colors.primary}
dropdown-item-selected
backgroundColor
{colors.primary-bg}
textColor
{colors.primary}
fontWeight
500
dropdown-item-danger
textColor
{colors.danger}
dropdown-item-danger-hover
backgroundColor
{colors.danger-bg}
textColor
{colors.danger}
dropdown-item-disabled
textColor
{colors.disabled-text}
cursor
not-allowed
dropdown-item-icon
iconSize
{icons.sizeMap.md}
iconColor
{colors.muted}
flexShrink
0
dropdown-item-icon-hover
iconColor
{colors.primary}
dropdown-item-icon-danger
iconColor
{colors.danger}
dropdown-item-label
flex
1
overflow
hidden
textOverflow
ellipsis
whiteSpace
nowrap
dropdown-item-description
fontSize
12px
textColor
{colors.muted}
marginTop
1px
overflow
hidden
textOverflow
ellipsis
whiteSpace
nowrap
dropdown-item-shortcut
fontSize
11px
fontWeight
400
textColor
{colors.muted}
marginLeft
auto
flexShrink
0
paddingLeft
{spacing.sm}
dropdown-item-separator
height
1px
backgroundColor
{colors.hairline}
marginY
{spacing.xs}
dropdown-item-section-heading
fontFamily
Geist
fontSize
11px
fontWeight
500
textColor
{colors.muted}
textTransform
uppercase
letterSpacing
0.06em
paddingX
{spacing.sm}
paddingY
{spacing.xs}
dropdown-item-checkbox
display
flex
alignItems
center
gap
{spacing.sm}
paddingX
{spacing.sm}
paddingY
{spacing.xs}
borderRadius
{rounded.sm}
fontFamily
Geist
fontSize
14px
fontWeight
400
lineHeight
1.40
textColor
{colors.ink}
cursor
pointer
minHeight
32px
userSelect
none
dropdown-item-checkbox-hover
backgroundColor
{colors.primary-bg}
textColor
{colors.primary}
dropdown-item-checkbox-focus
outline
2px solid {colors.border-focus}
outlineOffset
-2px
dropdown-item-checkbox-checked
backgroundColor
{colors.primary-bg}
dropdown-item-checkbox-disabled
textColor
{colors.disabled-text}
cursor
not-allowed
dropdown-item-checkbox-indicator
width
16px
height
16px
borderRadius
{rounded.sm}
borderWidth
1.5px
borderStyle
solid
borderColor
{colors.border-strong}
backgroundColor
{colors.surface-card}
flexShrink
0
display
flex
alignItems
center
justifyContent
center
dropdown-item-checkbox-indicator-checked
backgroundColor
{colors.primary}
borderColor
{colors.primary}
iconColor
{colors.primary-text}
iconSize
{icons.sizeMap.sm}
dropdown-item-checkbox-indicator-disabled
backgroundColor
{colors.disabled-bg}
borderColor
{colors.disabled-border}
dropdown-item-checkbox-label
flex
1
overflow
hidden
textOverflow
ellipsis
whiteSpace
nowrap
dropdown-item-checkbox-description
fontSize
12px
textColor
{colors.muted}
marginTop
1px
dropdown-item-single-select
display
flex
alignItems
center
gap
{spacing.sm}
paddingX
{spacing.sm}
paddingY
{spacing.xs}
borderRadius
{rounded.sm}
fontFamily
Geist
fontSize
14px
fontWeight
400
lineHeight
1.40
textColor
{colors.ink}
cursor
pointer
minHeight
32px
userSelect
none
dropdown-item-single-select-hover
backgroundColor
{colors.primary-bg}
textColor
{colors.primary}
dropdown-item-single-select-focus
outline
2px solid {colors.border-focus}
outlineOffset
-2px
dropdown-item-single-select-selected
backgroundColor
{colors.primary-bg}
textColor
{colors.primary}
fontWeight
500
dropdown-item-single-select-disabled
textColor
{colors.disabled-text}
cursor
not-allowed
dropdown-item-single-select-check
width
{icons.sizeMap.md}
height
{icons.sizeMap.md}
flexShrink
0
iconColor
{colors.primary}
opacity
0
dropdown-item-single-select-check-visible
opacity
1
dropdown-item-single-select-label
flex
1
overflow
hidden
textOverflow
ellipsis
whiteSpace
nowrap
dropdown-item-single-select-description
fontSize
12px
textColor
{colors.muted}
marginTop
1px
dropdown-item-single-select-leading-icon
iconSize
{icons.sizeMap.md}
iconColor
{colors.muted}
flexShrink
0

Known gaps

  • Nested sub-menu item (item that opens a child menu) not yet specified.
  • Item with avatar (e.g. user list item) not yet specified.