-
Notifications
You must be signed in to change notification settings - Fork 207
feat(action-menu): S2 migration [CSS-1160] #4085
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: spectrum-two
Are you sure you want to change the base?
feat(action-menu): S2 migration [CSS-1160] #4085
Conversation
📚 Branch previewPR #4085 has been deployed to Azure Blob Storage: https://spectrumcss.z13.web.core.windows.net/pr-4085/index.html. |
File metricsSummaryTotal size: 1.44 MB* Table reports on changes to a package's main file. Other changes can be found in the collapsed Details section below.
File change detailsactionbutton
actiongroup
actionmenu
menu
* An ASCII character in UTF-8 is 8 bits or 1 byte. |
2729f84
to
779e411
Compare
🦋 Changeset detectedLatest commit: 2aed50b The changes in this PR will be included in the next version bump. This PR includes changesets to release 6 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
635f709
to
242929c
Compare
4baa099
to
eb8cde2
Compare
313ee43
to
3babcfa
Compare
4d618da
to
f3fa4d4
Compare
f2ef53c
to
409436c
Compare
dbd613f
to
00038a9
Compare
d1e6569
to
1ddcb45
Compare
currentStep = 2, | ||
totalStepCount = 8, | ||
isOpen = false, | ||
alt = "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixing an a11y feedback note from Chromatic.
fill, | ||
id = getRandomId("icon"), | ||
customClasses = [], | ||
customStyles = {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw a regression in the icon VRTs where the fill was inheriting to all icons due to the custom property's inheritance.
labelledby: { table: { disable: true } }, | ||
items: { table: { disable: true } }, | ||
role: { table: { disable: true } }, | ||
subrole: { table: { disable: true } }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Subrole ended up being easier to intuit from the role instead of passing it through from the parent.
)} | ||
</ul> | ||
`, | ||
Template: ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Letting the template handle this logic because it's a bit duplicative to redefine it here and could lead to mismatches.
testHeading: "No selection, with thumbnails", | ||
description: undefined, | ||
thumbnailUrl: "thumbnail.png" | ||
hasThumbnail: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since thumbnail.png is the default, just the hasThumbnail is sufficient.
isCollapsible = false, | ||
label, | ||
rootClass, | ||
role, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Labels can have roles too! 🥳
return html` | ||
<span | ||
role=${ifDefined(role)} | ||
id=${ifDefined(id)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need the id and role for switch labels.
hasExternalLink = false, | ||
hasActions = false, | ||
id = getRandomId("menuitem"), | ||
labelId = getRandomId("menuitem-label"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
label id lets us connect the switch input field with the already present label for the menu item
1ddcb45
to
4a2cfe1
Compare
748e3cb
to
76988b3
Compare
"a.spectrum-ActionButton" | ||
], | ||
"modifiers": [ | ||
"--mod-actionbutton-animation-duration", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is for S2 and we've agreed to remove modifiers, I removed the mods on any lines I needed to update for this change anyway.
e4bf910
to
46a8a1b
Compare
} | ||
|
||
/* Focus indicator */ | ||
.spectrum-ActionButton { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just me tidying up a bit by combining these styles in with the initial definition for .spectrum-ActionButton
.spectrum-Menu-itemCheckbox { | ||
grid-area: checkmarkArea; | ||
} | ||
&.is-selectableMultiple:not(:has(.is-selectable)) .spectrum-Menu-itemCheckbox { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this not to prevent clash with the is-selectable placement.
46a8a1b
to
75c284c
Compare
import { Template as Menu } from "@spectrum-css/menu/stories/template.js"; | ||
import { Template as Popover } from "@spectrum-css/popover/stories/template.js"; | ||
import { getRandomId } from "@spectrum-css/preview/decorators"; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we import the css file here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OH! Yes great idea. 😜
|
||
.spectrum-ActionMenu-popover { | ||
/* @passthrough */ | ||
--spectrum-popover-animation-distance: var(--spectrum-actionmenu-button-to-menu-gap); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the popover template is setting the transform and overriding the popover CSS. Which makes it look great! But that means it's not using that passthrough to popover from actionmenu/index.css.

Would it work to use --spectrum-popover-animation-distance
instead of --spectrum-spacing-100
for the transform in the popover template so this passthrough gets picked up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooooh yes. I will try that!
* Action menu allows users to access and execute various commands or tasks related to their current workflow. It's typically triggered from an action button by user interaction. | ||
* | ||
* Note that the accessibility roles are different for an action menu compared to a normal menu. The action menu is a combination of a menu, popover, and action button. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be the same description that appears for the default story as well, we could probably eliminate one of these!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Touche!
* By default, the menu is opened by pressing the trigger element or activating it via the <kbd>Space</kbd> or <kbd>Enter</kbd> keys. However, there may be cases where the trigger should perform a separate action on press such as selection, and should only display the menu when long pressed. For this use-case, the menu will only be opened when pressing and holding the trigger or by using the <kbd>Option</kbd> (Alt on Windows) + <kbd>Down arrow</kbd>/<kbd>Up arrow</kbd> keys while focusing the trigger. | ||
* | ||
* This example illustrates the expected visuals and states of the action menu for a trigger with both long press and short press behaviors. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😍 love this description!
I don't see the long press working here (I can't access the menu for long press), but I don't think we expect it to, is that correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I took a first pass at making the long-press functional and then thought, this feels a little out-of-scope. Do you think it's worth making it work or should I just note that it doesn't work in CSS but does in SWC?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed what I thought was maybe a regression for the Media Options story on the Coachmark docs page:
The container has a height being set on it in the customStyles
, wondering if removing that would help?
I couldn't figure out what would have introduced it here though, and I assumed it was a regression from something in this branch because I don't see it in the spectrum-two
branch preview.
But I do see the same issue when I run spectrum-two
locally so I'm wondering if it's something from #4174 maybe, since it looks like that's where the need for some of those explicit dimensions on popover was eliminated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a side note, I also have been noticing some weirdness here, but it's inconsistent so I'm not sure what we should do about it. Sometimes when I open the coachmark component story (on local or preview) the height or sometimes width of the component increases infinitely. It doesn't happen every time, but I'm thinking it's triggered if I open the Coachmark Default story after the Action menu story (I was able to replicate in Firefox, Chrome, and Safari).

It also happens in popover, also if I click into the Popover story after Action menu:

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, Steph saw some of that too until she'd done a hard refresh. I wonder if it's an inconsistent bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the accessibility improvements that are mentioned in the changeset for menu but I don't really see updates to some of these other items (forced-colors, focus indicator, cjk), am I looking in the right place?
Menu refinements
Updates
@spectrum-css/menu
styles to align with latest Spectrum 2 design specifications and improve accessibility.
- Focus indicator tokens wired through: width, color, gap/offset, and outline style.
- CJK line-height tokens applied for labels, descriptions, and section headers.
- External link and drill‑in icon sizing variables exposed; thumbnail sizing and alignment refined.
- Forced-colors improvements and readability adjustments.
- Non-breaking; no class or DOM changes required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I wonder if I pulled some of that back and forgot to update the changeset. I'll double check.
|
||
/* | ||
* @spectrum-css/actionmenu | ||
* This component is a combination of a menu, popover, and action button. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is more related to popover, which wasn't changed in this PR:
I see the button jumping a bit (for bottom-start it moves down and to the right) when I click it, I think it's related to the previous popover positioning (alliteration always!) work and doesn't seem intentional:
Screen.Recording.2025-09-25.at.12.01.12.PM.mov
If I pull down spectrum-two
, I can also see the issue there:
Screen.Recording.2025-09-25.at.12.08.30.PM.mov
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
&.is-selected { | ||
/* expanded is specific to action menu when the menu is open */ | ||
&:where(.is-selected, [aria-pressed="true"], [aria-expanded="true"]) { | ||
--mod-actionbutton-background-color-default: var(--mod-actionbutton-background-color-default-selected, var(--spectrum-neutral-background-color-selected-default)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this update component properties instead of mods, or is it a case where it hits an issue going into SWC environment?
Either way - a good case to flag for our upcoming discussions around this 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That said - I also don't see this change in the Action Menu tokens, possibly because "selected" is a different state/intent than "expanded"? Should we double-check with design if this should take on the darker background?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, action button should be our first attempt to introduce layers I suspect because it is riddled with specificity battles and often hooking the modifiers was the only way to ensure properties updated in context.
}; | ||
|
||
/** | ||
* Action menus can be positioned in four locals relative to the trigger but <u>only one menu can be triggered at a single time</u>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] perhaps switch to <em>
since underlines usually indicate a link?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great point! Updating this now.
14468b0
to
22ccfc9
Compare
22ccfc9
to
2aed50b
Compare
Description
This PR:
@spectrum-css/actionmenu
component that composesActionButton
,Popover
, andMenu
to present action lists from a trigger.@spectrum-css/actionbutton
and@spectrum-css/actiongroup
to treat selection via.is-selected
as well as:where([aria-pressed="true"], [aria-expanded="true"])
to cover more accessibility use-cases while keeping selector specificity low.@spectrum-css/menu
to align with Spectrum 2 specifications and accessibility improvements.Design references:
Includes a changeset with the following bumps:
How and where has this been tested?
Action menu
stories (default, long-press, placements).Menu
stories for focus indicators, CJK line-height, external link/drill-in icons, thumbnails, and forced-colors behavior.Action button
andAction group
selected visuals using.is-selected
,[aria-pressed="true"]
, and[aria-expanded="true"]
.Validation steps
isOpen
and confirm popover/menu spacing and placement reflect updates..is-selected
, setaria-pressed="true"
, andaria-expanded="true"
; confirm identical visuals due to:where(...)
..is-selected
and ARIA attributes.Screenshots
To-do list
Notes for reviewers
:where([aria-pressed],[aria-expanded])
to avoid specificity issues and broaden accessibility support.References
https://github.com/changesets/changesets
https://www.figma.com/design/eoZHKJH9a3LJkHYCGt60Vb/S2-Token-specs?node-id=19758-3424