Skip to content

Conversation

castastrophe
Copy link
Collaborator

@castastrophe castastrophe commented Jul 29, 2025

Description

This PR:

  • Adds a new @spectrum-css/actionmenu component that composes ActionButton, Popover, and Menu to present action lists from a trigger.
  • Updates @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.
  • Refines @spectrum-css/menu to align with Spectrum 2 specifications and accessibility improvements.

Design references:

  • Figma S2 token specs: link

Includes a changeset with the following bumps:

  • @spectrum-css/actionmenu: major (new component)
  • @spectrum-css/actionbutton: minor (selection semantics with ARIA via :where)
  • @spectrum-css/menu: patch (S2 refinements, accessibility)
  • @spectrum-css/actiongroup: patch (selection semantics alignment)

How and where has this been tested?

  • Storybook locally:
    • Verified Action menu stories (default, long-press, placements).
    • Verified Menu stories for focus indicators, CJK line-height, external link/drill-in icons, thumbnails, and forced-colors behavior.
    • Verified Action button and Action group selected visuals using .is-selected, [aria-pressed="true"], and [aria-expanded="true"].
  • Forced Colors (Windows High Contrast) visual pass in Storybook.
  • Chromatic/VRT pending reviewer confirmation.

Validation steps

  1. Open Storybook for Action menu:
    • Toggle isOpen and confirm popover/menu spacing and placement reflect updates.
    • Enable “Long press” and confirm press vs long-press behavior in docs.
  2. Open Storybook for Action button:
    • Toggle .is-selected, set aria-pressed="true", and aria-expanded="true"; confirm identical visuals due to :where(...).
  3. Open Storybook for Action group:
    • In compact group, confirm hover/selected/focus ring layering and selection visuals via .is-selected and ARIA attributes.
  4. Open Storybook for Menu:
    • Confirm external-link and drill‑in icon sizing; thumbnail sizing/alignment.
    • Confirm forced-colors readability.

Screenshots

  • Add Storybook screenshots for:
    • Action menu default and long-press
    • Action button selected (class vs ARIA)
    • Menu focus and forced-colors states

To-do list

  • I have read the contribution guidelines.
  • I have updated relevant Storybook stories and templates.
  • I have tested these changes in Windows High Contrast mode.
  • If my change impacts other components, I have tested to make sure they don't break.
  • If my change impacts documentation, I have updated the documentation accordingly.
  • I have included a well-written changeset if my change needs to be published.

Notes for reviewers

  • No class name changes; selection semantics expanded via :where([aria-pressed],[aria-expanded]) to avoid specificity issues and broaden accessibility support.
  • Menu refinements include focus margin reservation, CJK line-height variables, transparent-at-rest backgrounds per S2, and forced-colors improvements.

References

  • Changesets documentation: https://github.com/changesets/changesets
  • Figma S2 token specs: https://www.figma.com/design/eoZHKJH9a3LJkHYCGt60Vb/S2-Token-specs?node-id=19758-3424

@castastrophe castastrophe changed the title feat(action-menu): S2 migration feat(action-menu): S2 migration [CSS-1160] Jul 29, 2025
Copy link
Contributor

github-actions bot commented Jul 29, 2025

📚 Branch preview

PR #4085 has been deployed to Azure Blob Storage: https://spectrumcss.z13.web.core.windows.net/pr-4085/index.html.

Copy link
Contributor

github-actions bot commented Jul 29, 2025

File metrics

Summary

Total size: 1.44 MB*
Total change (Δ): 🔴 ⬆ 0.83 KB (0.05%)

Table reports on changes to a package's main file. Other changes can be found in the collapsed Details section below.

Package Size Minified Gzipped Δ
actionbutton 23.62 KB 22.53 KB 2.99 KB 🟢 ⬇ 0.04 KB
actiongroup 7.73 KB 7.41 KB 1.09 KB 🔴 ⬆ 0.06 KB
actionmenu 0.84 KB 🆕 0.83 KB 🆕 0.48 KB 🆕 0.84 KB
menu 47.47 KB 45.21 KB 5.00 KB 🟢 ⬇ 0.45 KB

File change details

actionbutton

Filename Head Minified Gzipped Compared to base
index.css 23.62 KB 22.53 KB 2.99 KB 🟢 ⬇ 0.04 KB
metadata.json 10.52 KB - - 🔴 ⬆ 0.34 KB

actiongroup

Filename Head Minified Gzipped Compared to base
index.css 7.73 KB 7.41 KB 1.09 KB 🔴 ⬆ 0.06 KB
metadata.json 3.33 KB - - 🔴 ⬆ 0.06 KB

actionmenu

Filename Head Minified Gzipped Compared to base
index.css 0.84 KB 🆕 0.83 KB 🆕 0.48 KB 🆕 0.84 KB
metadata.json 0.31 KB - - 🆕 0.31 KB

menu

Filename Head Minified Gzipped Compared to base
index.css 47.47 KB 45.21 KB 5.00 KB 🟢 ⬇ 0.45 KB
metadata.json 23.43 KB - - 🟢 ⬇ 0.52 KB
* Size is the sum of all main files for packages in the library.
* An ASCII character in UTF-8 is 8 bits or 1 byte.

@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch from 2729f84 to 779e411 Compare July 30, 2025 20:23
Copy link

changeset-bot bot commented Jul 30, 2025

🦋 Changeset detected

Latest commit: 75c284c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@spectrum-css/actionmenu Major
@spectrum-css/actionbutton Minor
@spectrum-css/menu Patch
@spectrum-css/actiongroup Patch
@spectrum-css/bundle Patch
@spectrum-css/preview Patch

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

@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch 3 times, most recently from 635f709 to 242929c Compare August 1, 2025 20:06
@castastrophe castastrophe marked this pull request as ready for review August 1, 2025 20:06
@castastrophe castastrophe self-assigned this Aug 1, 2025
@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch 2 times, most recently from 4baa099 to eb8cde2 Compare August 4, 2025 15:23
@castastrophe castastrophe added size-2 S ~6-18hrs; not hard or time consuming, one or two work days to complete. wip This is a work in progress, don't judge. run_vrt For use on PRs looking to kick off VRT S2 Spectrum 2 labels Aug 4, 2025
@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch 4 times, most recently from 313ee43 to 3babcfa Compare August 6, 2025 23:43
@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch 2 times, most recently from 4d618da to f3fa4d4 Compare August 7, 2025 16:14
@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch 3 times, most recently from f2ef53c to 409436c Compare August 18, 2025 16:08
@adobe adobe deleted a comment from github-actions bot Aug 18, 2025
@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch 2 times, most recently from dbd613f to 00038a9 Compare August 18, 2025 17:12
@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch 10 times, most recently from 96a7093 to d1e6569 Compare September 2, 2025 16:33
@castastrophe castastrophe added ready-for-review and removed wip This is a work in progress, don't judge. labels Sep 2, 2025
@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch from d1e6569 to 1ddcb45 Compare September 2, 2025 17:03
@@ -23,6 +23,7 @@ export const CoachContainer = (
currentStep = 2,
totalStepCount = 8,
isOpen = false,
alt = "",
Copy link
Collaborator Author

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.

@@ -39,6 +39,7 @@ export const Template = ({
fill,
id = getRandomId("icon"),
customClasses = [],
customStyles = {},
Copy link
Collaborator Author

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.

@@ -78,15 +78,12 @@ export default {
labelledby: { table: { disable: true } },
items: { table: { disable: true } },
role: { table: { disable: true } },
subrole: { table: { disable: true } },
Copy link
Collaborator Author

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: ({
Copy link
Collaborator Author

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.

@@ -133,14 +127,14 @@ export const MenuItemGroup = Variants({
{
testHeading: "No selection, with thumbnails",
description: undefined,
thumbnailUrl: "thumbnail.png"
hasThumbnail: true,
Copy link
Collaborator Author

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.

@@ -37,27 +41,38 @@ const Label = ({
isCollapsible = false,
label,
rootClass,
role,
Copy link
Collaborator Author

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)}
Copy link
Collaborator Author

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.

@@ -258,6 +274,7 @@ export const MenuItem = (
hasExternalLink = false,
hasActions = false,
id = getRandomId("menuitem"),
labelId = getRandomId("menuitem-label"),
Copy link
Collaborator Author

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

@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch from 1ddcb45 to 4a2cfe1 Compare September 2, 2025 17:25
@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch 3 times, most recently from 748e3cb to 76988b3 Compare September 10, 2025 14:15
".spectrum-ActionButton:not(:has(.spectrum-ActionButton-label))",
"a.spectrum-ActionButton"
],
"modifiers": [
"--mod-actionbutton-animation-duration",
Copy link
Collaborator Author

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.

@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch 7 times, most recently from e4bf910 to 46a8a1b Compare September 19, 2025 17:14
color: inherit;
transform: var(--spectrum-logical-rotation);
}

/* Focus indicator */
.spectrum-ActionButton {
Copy link
Collaborator Author

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 {
Copy link
Collaborator Author

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.

@castastrophe castastrophe force-pushed the castastrophe/feat-action-menu-migration branch from 46a8a1b to 75c284c Compare September 19, 2025 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready-for-review run_vrt For use on PRs looking to kick off VRT S2 Spectrum 2 size-2 S ~6-18hrs; not hard or time consuming, one or two work days to complete.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants