Context Menu
Thirty-four variants across five components. Four menus, twenty-eight rows, a submenu trigger, a heading and a rule.
Radio reuses the Show Icon axis for its tick rather than for a leading glyph, which is why the control above renames itself. A radio row also carries a fixed 20px spacer at the end, so a checked and an unchecked option line up down the right-hand edge.
Light or dark, solid or see-through
280 by 360 at radius 10, a 1px border and two stacked shadows. Colour swaps the surface between white and #262626 and takes the ink with it; Appearance drops that surface to 70%. Hover a row below: the highlight follows the menu rather than fighting it.
The hover fills for Default / Translucent and Inverted / Solid had been swapped. The light translucent menu hovered to near-black under near-black text, and the dark solid menu hovered to white under near-white text: contrast ratios of 1.06 and 1.02, which is to say the label disappeared under the cursor in both. They are now the right way round, and the light translucent surface itself, which was fully opaque and identical to Solid, drops to 70% like its inverted counterpart.
Destructive / Hover had the same fault a third time: the row filled with base.destructive and the label and icon stayed base.destructive, red on red. Both now take base.destructive-foreground, and the shortcut comes with them rather than staying dark.
A submenu trigger, a heading and a rule
Active fills the row and moves every ink to base.secondary-foreground, the same treatment Hover gives an ordinary item. A submenu that is open should look no different from one you are pointing at.
12 at weight 500 in base.muted-foreground, with the same 8px side padding as a row so the heading and the items it covers share a left edge.
A 1px rule inside an 8px board, so the space above and below comes with it and you do not have to remember to add margin around a hairline.
Ten menus, from three rows to eleven
The second frame is 964 by 1372. The copy is the file's; the radio menus below are live.
Five components, thirty-four variants
Read straight out of the Penpot file. The axes below are the property names you will see in the variant dropdown.
Using the Context Menu
Because Radio reuses the Show Icon axis for its tick instead of for a leading glyph. A radio row is text, then a check, then a fixed 20px spacer, so a chosen and an unchosen option keep the same right edge. It is the one place in the component where an axis name does not describe what it draws.
A destructive row is either offered or it is not there. The file draws it at rest, in red on the menu surface, and hovered, where the whole row fills with base.destructive and the label goes white. Disabling it rather than removing it would leave a red row nobody can press, which reads as a fault.
The hover fill on a row inside a translucent menu, at 70% rather than solid so the surface behind it still shows. It is base.muted carrying the alpha, which is why the row lightens without hiding what the menu is floating over.
It is 312 wide rather than 300 and ends in a chevron. Its Active state gives it exactly what Hover gives an ordinary item, a base.muted fill and base.secondary-foreground ink, so an open submenu and a pointed-at row look the same. That is deliberate: both mean the same thing to the reader.