Skip to content
SuperCoach

Components · Actions

Context menu

Beta

A right-click menu for power users, such as in the program builder.

Day 3 · Upper body5 exercises · 50 minRight-click or long-press for options

When to use

  • As a shortcut for people who work in a dense area all day: right-click a session in the program builder, a cell in the meal-plan grid, a row in a long list.
  • Only for actions that are also available somewhere visible: a Dropdown menu on the same item, or buttons.

When not to use

  • As the only way to reach an action. Many people never right-click, touch users have to long-press, and screen reader users won't find it. Put the same actions in a "More" dropdown menu.
  • On ordinary links, text and form fields, where people expect the browser's own menu (copy, open in new tab, spell-check).
  • For one or two actions: show them as buttons.

Anatomy

Day 3 · Upper bodyRight-click or long-press
  1. 1. Trigger area: the item it acts on; opens the menu at the pointer
  2. 2. Label (optional): names the item
  3. 3. Item: optional 16px icon, then a verb
  4. 4. Destructive item: last, after a separator

Right-click or long-press the area in the example to see parts 2 to 4.

Variants

Program calendar · MarchRight-click or long-press to change the view

A context menu has the same item types as the Dropdown menu: actions, variant="destructive", checkbox items, a radio group, one level of submenu, labels, separators and shortcuts. The example shows view options for the program calendar. Only show a shortcut if it really works in that view.

States

StateWhat changesToken
OpenMenu panel at the pointer, on the dropdown layerbg-popover, shadow-md, z-(--z-dropdown)
Highlighted itemAccent fill and textbg-accent, text-accent-foreground
Open submenu triggerStays highlighted while its submenu is opendata-[state=open]:bg-accent
CheckedCheck mark (checkbox) or dot (radio) at the startItemIndicator
Disabled itemHalf opacity, skipped by arrow keys. "Paste" in the first example is disabled because nothing has been copiedopacity-(--opacity-disabled)
Destructive itemRed text and icon; a red tint when highlightedtext-destructive-text, bg-destructive/10

As in the dropdown menu, destructive items use text-destructive-text, which stays above 4.5:1 on their 10% tint when highlighted. Upstream's text-destructive dropped to about 4.1:1 there.

The trigger area has no style of its own. Give it a visible focus ring if it is focusable, as the examples do with ring-ring/50.

Usage guidelines

Day 3 · Upper body
Do.The session also has a visible More button with the same actions. The context menu is a shortcut on top.
Day 3 · Upper body
Don't.Actions only on right-click, with no visible way in. Touch, keyboard and screen reader users won't find them.
  • Keep the items and their order the same as the item's dropdown menu, so both are learned once.
  • Put the most frequent actions first and destructive actions last, after a separator.
  • Don't replace the browser's menu on text people may want to copy.

Content guidelines

  • Same rules as the Dropdown menu: verb first, sentence case, "…" when a dialog follows.
  • Keep labels short; the menu opens at the pointer and covers the content around it.
  • Arabic: "تعديل الحصة"، "تكرار إلى"، "حذف الحصة".

Accessibility

KeyDoes
Shift+F10 or the Menu keyOpens the menu when the trigger area has focus (the browser fires the contextmenu event)
Arrow up / downMoves between items, skipping disabled ones
Arrow right (left in RTL), Enter or SpaceOn a submenu trigger: opens the submenu
Arrow left (right in RTL), Escape in a submenuCloses the submenu
Enter or SpaceChooses the item. Checkbox and radio items toggle
EscapeCloses the menu
  • Long-press opens it on touch screens (after 700ms); the trigger blocks the browser's own long-press menu.
  • The trigger area is a plain <span> and isn't focusable by default. Add tabIndex={0} and a focus style, or wrap an element that already takes focus, so Shift+F10 works.
  • The panel is a menu with menuitem, menuitemcheckbox and menuitemradio items. A screen reader announces "menu" and the first item when it opens, but nothing announces that a context menu exists. That is why the actions must also be reachable another way.

RTL

  • The menu opens at the pointer and is kept inside the viewport, so placement doesn't depend on direction.
  • Icons and check marks sit at the start of each item and move to the right. Shortcuts sit at the end. Submenus open toward the left.
  • Arrow keys follow the direction because the site provides Radix's DirectionProvider.
  • The submenu chevron mirrors, so it points left in RTL, toward where the submenu opens.

Tokens used

Read from components/ui/context-menu.tsx at build time, so this list changes when the component does. Opacity modifiers such as /90 are shadcn hover and focus tints on top of the token.

Semantic color tokens used by this component
TokenUtilitiesSuperCoachCoach
--accentbg-accentbrand-50orange-50
--accent-foregroundtext-accent-foregroundbrand-700orange-700
--borderbg-borderneutral-200neutral-200
--destructivebg-destructive/10 text-destructivered-600red-600
--destructive-texttext-destructive-textred-700red-700
--foregroundtext-foregroundneutral-950neutral-950
--muted-foregroundtext-muted-foregroundneutral-600neutral-600
--popoverbg-popoverwhitewhite
--popover-foregroundtext-popover-foregroundneutral-950neutral-950
  • Layerz-(--z-dropdown)
  • Opacityopacity-(--opacity-disabled)
  • Radiusrounded-md
  • Radiusrounded-sm
  • Shadowshadow-lg
  • Shadowshadow-md
  • Typefont-medium
  • Typetext-sm
  • Typetracking-wide
  • Typetext-xs

Props

<ContextMenu>

Also takes every prop of Radix ContextMenu.Root

No props of its own.

<ContextMenuTrigger>

Also takes every prop of Radix ContextMenu.Trigger

No props of its own.

<ContextMenuSubTrigger>

Also takes every prop of Radix ContextMenu.SubTrigger

ContextMenuSubTrigger props
PropTypeDefault
inset?boolean—

<ContextMenuContent>

Also takes every prop of Radix ContextMenu.Content

No props of its own.

<ContextMenuItem>

Also takes every prop of Radix ContextMenu.Item

ContextMenuItem props
PropTypeDefault
inset?boolean—
variant?"default" | "destructive""default"

<ContextMenuCheckboxItem>

Also takes every prop of Radix ContextMenu.CheckboxItem

No props of its own.

<ContextMenuRadioItem>

Also takes every prop of Radix ContextMenu.RadioItem

No props of its own.

Replaces in coach-admin

From the read-only audit of coach-admin: 5 style values, 5 uses.

The only context menu in coach-admin is ReactGrid's, restyled in src/reusableComponents/sheet/ReactGridCustom.scss for the spreadsheet view. It is drawn by the grid library, so it changes only if the grid is replaced; these classes show which values it should match.

Classes and selectors

  • .rg-context-menu3
  • .rg-context-menu-option2

SCSS variables in these styles

  • $shadow-colornot a color: spacing, size or layout
  • $opacity-20not a color: spacing, size or layout
  • $dropdown-menu-bg-colornot a color: spacing, size or layout
  • $context-menu-font-sizenot a color: spacing, size or layout
  • $context-menu-option-paddingnot a color: spacing, size or layout
  • $context-menu-shadownot a color: spacing, size or layout

Dropdown menu, Table, Button.