Skip to content

docs(actiongroup): complete migration plan#6412

Open
rise-erpelding wants to merge 2 commits into
mainfrom
rise-erpelding/swc-2214-action-group-migration-plan
Open

docs(actiongroup): complete migration plan#6412
rise-erpelding wants to merge 2 commits into
mainfrom
rise-erpelding/swc-2214-action-group-migration-plan

Conversation

@rise-erpelding

Copy link
Copy Markdown
Collaborator

Description

Phase 1 (preparation) of the 1st-gen to 2nd-gen swc-action-group migration. Adds the component migration plan to CONTRIBUTOR-DOCS and updates the migration status table.

The plan covers:

  • 1st-gen API surface. All properties, methods, events, slots, CSS custom properties, and rendered shadow DOM documented from source.
  • Breaking changes (B1–B11). verticalorientation rename with 1st-gen deprecation notice; --mod-* custom properties dropped; host role fixed to role="group" in all modes; child roles fixed to role="button" only (no radio/checkbox); RovingTabindexController replaced by FocusgroupNavigationController; change event ordering fix (SWC-889); label required warning when selects is set (SWC-1121); focus z-index fix (SWC-1342).
  • Additive items (A1–A3). Group-level emphasized propagation (deferred pending action-button); consumer guidance for future swc-segmented-control / swc-toggle-button-group alternatives; orientation="both" extension.
  • 2nd-gen API decisions. Full property table with decision status (Confirmed / Inferred / Dropped) and supporting sources.
  • Behavioral semantics. Selection management (selects modes, aria-pressed vs aria-checked), compact mode position-attribute mechanism (data-group-position), focus management, child propagation, change event ordering, cancelation timing (queueMicrotask pattern), and re-enable reconciliation for selects="single".
  • Architecture. Core/SWC split with planned file layout and ownership boundaries.
  • Migration checklist. Preparation through review phases, including 1st-gen deprecation notices and a deferred implementation tickets table.

Motivation and context

Planning output for SWC-2214. The migration plan is the required Phase 1 artifact; no implementation work proceeds without it.

Related issue(s)

  • SWC-2214: Analyze component and create migration plan
  • SWC-2212: Action Group 2nd-gen migration epic

Screenshots (if appropriate)

N/A — documentation only.

Author's checklist

  • I have read the CONTRIBUTING and PULL_REQUESTS documents.
  • I have reviewed at the Accessibility Practices for this feature, see: Aria Practices
  • I have added automated tests to cover my changes.
  • I have included a well-written changeset if my change needs to be published.
  • I have included updated documentation if my change required it.

Reviewer's checklist

  • Includes a Github Issue with appropriate flag or Jira ticket number without a link
  • Includes thoughtfully written changeset if changes suggested include patch, minor, or major features
  • Automated tests cover all use cases and follow best practices for writing
  • Validated on all supported browsers
  • All VRTs are approved before the author can update Golden Hash

Manual review test cases

  • Migration plan is accurate and complete

    1. Open CONTRIBUTOR-DOCS/03_project-planning/03_components/action-group/migration-plan.md.
    2. Verify the 1st-gen API surface matches 1st-gen/packages/action-group/src/ActionGroup.ts.
    3. Verify breaking changes B1–B11 align with the accessibility migration analysis and action-button PR feat(action-button): S2 migration #6340.
    4. Verify the architecture split (core vs SWC) matches the pattern established by the badge migration reference.
  • Status table updated

    1. Open CONTRIBUTOR-DOCS/03_project-planning/02_workstreams/02_2nd-gen-component-migration/01_status.md.
    2. Confirm the Action Group row shows Analyze ✓ and Factor Component ✓ (plan complete).

Device review

  • Did it pass in Desktop?
  • Did it pass in (emulated) Mobile?
  • Did it pass in (emulated) iPad?

Accessibility testing checklist

No interactive code changes. The plan documents the accessibility requirements for the implementation phases; no runtime behavior to test here.

  • Keyboard — not applicable; documentation-only change.
  • Screen reader — not applicable; documentation-only change.

@changeset-bot

changeset-bot Bot commented Jun 16, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 8454587

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@rise-erpelding rise-erpelding marked this pull request as ready for review June 16, 2026 20:13
@rise-erpelding rise-erpelding requested a review from a team as a code owner June 16, 2026 20:13
@rise-erpelding rise-erpelding added Component:Action group Status:Ready for review PR ready for review or re-review. 2nd gen These issues or PRs map to our 2nd generation work to modernizing infrastructure. labels Jun 16, 2026
@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

📚 Branch Preview Links

🔍 First Generation Visual Regression Test Results

When a visual regression test fails (or has previously failed while working on this branch), its results can be found in the following URLs:

Deployed to Azure Blob Storage: pr-6412

If the changes are expected, update the current_golden_images_cache hash in the circleci config to accept the new images. Instructions are included in that file.
If the changes are unexpected, you can investigate the cause of the differences and update the code accordingly.


- `swc-action-group` is a composite keyboard control: one Tab stop into the strip, arrow-key navigation among children via `FocusgroupNavigationController`, and optional managed selection (`selects="single|multiple"`). It is substantially more complex than `swc-button-group`, which has no roving tabindex.
- Three ARIA-breaking changes ship in this migration: host is always `role="group"` (never `toolbar` or `radiogroup`); children are always `role="button"` (never `radio` or `checkbox`); selection state is exposed via `aria-pressed`/`aria-checked` on the button's focus target rather than through host or child role changes.
- The `selects` API is retained. `swc-action-group` is the appropriate home for selection behavior until `swc-segmented-control` and `swc-toggle-button-group` exist in 2nd-gen. Consumer chooses the right component for their UX; action-group does not mandate a migration to those alternatives.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we definitely doing a toggle button group eventually? Accessibility analysis mentions it too but just want to double-confirm.

- `swc-action-group` is a composite keyboard control: one Tab stop into the strip, arrow-key navigation among children via `FocusgroupNavigationController`, and optional managed selection (`selects="single|multiple"`). It is substantially more complex than `swc-button-group`, which has no roving tabindex.
- Three ARIA-breaking changes ship in this migration: host is always `role="group"` (never `toolbar` or `radiogroup`); children are always `role="button"` (never `radio` or `checkbox`); selection state is exposed via `aria-pressed`/`aria-checked` on the button's focus target rather than through host or child role changes.
- The `selects` API is retained. `swc-action-group` is the appropriate home for selection behavior until `swc-segmented-control` and `swc-toggle-button-group` exist in 2nd-gen. Consumer chooses the right component for their UX; action-group does not mandate a migration to those alternatives.
- Compact mode border-radius is handled entirely in CSS: action-group uses `::slotted(:first-child)` and `::slotted(:last-child)` to set `--swc-action-button-border-*-radius` custom properties, which cascade into action-button's shadow DOM. No JS attribute propagation needed; action-button must expose those properties as overridable fallbacks in its shadow CSS.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally it thought adding a data-group-position attribute was the best way to handle styling, this is a bit more aligned with how we handled accordion.


| # | What changes | 1st-gen behavior | 2nd-gen behavior | Consumer migration path |
| --- | ------------ | ---------------- | ---------------- | ----------------------- |
| **B1** | `vertical` boolean → `orientation` attribute | `vertical` boolean; no default | `orientation="horizontal"` default, `orientation="vertical"` | Replace `<sp-action-group vertical>` with `<swc-action-group orientation="vertical">`. Confirmed: matches button-group PR #6395 convention. 1st-gen `vertical` gets `@deprecated` JSDoc + `window.__swc.warn()` runtime warning. |

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aligns with button-group - since this hasn't hit main yet it's referencing the PR, should it?

| -------- | ---- | ------- | --------- | ----- |
| `compact` | `boolean` | `false` | `compact` | **Confirmed** (Figma). Figma labels this "Density: Compact". Buttons visually join; shared borders collapse. Quiet mode disables compact styling (same as 1st-gen). |
| `disabled` | `boolean` | `false` | `disabled` | **Confirmed** (a11y analysis). New in 2nd-gen. Uses `aria-disabled="true"` on host and propagates to children; children remain keyboard-reachable per APG guidance (SWC-621). |
| `justified` | `boolean` | `false` | `justified` | **Inferred** (SWC convention). Children fill available width equally. React S2 uses `isJustified`; 2nd-gen SWC convention drops the `is` prefix on booleans; `justified` follows that pattern. |

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in the design spec but I guess observed by spectrum-css and React

@5t3ph 5t3ph left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Putting "Request changes" because we may need group discussion/React insight on deferring/removing selection + if/when we will add toggle button group.


### Behavioral semantics

#### Selection management

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be removed entirely or at least deferred since the underlying ability of some sort of identifier for action buttons was also deferred (see value notes).

React does not have this ability, either, and it also would feel odd to have this and then pull it back when toggle button group is available.

@cdransf cdransf left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks awesome! Just had one question ✨

## TL;DR

- `swc-action-group` is a composite keyboard control: one Tab stop into the strip, arrow-key navigation among children via `FocusgroupNavigationController`, and optional managed selection (`selects="single|multiple"`). It is substantially more complex than `swc-button-group`, which has no roving tabindex.
- Three ARIA-breaking changes ship in this migration: host is always `role="group"` (never `toolbar` or `radiogroup`); children are always `role="button"` (never `radio` or `checkbox`); selection state is exposed via `aria-pressed`/`aria-checked` on the button's focus target rather than through host or child role changes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make the split between aria-pressed/aria-checked a bit clearer since button should only have aria-pressed? (It looks like we use the / as an either or like this elsewhere in the plan) ✨

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2nd gen These issues or PRs map to our 2nd generation work to modernizing infrastructure. Component:Action group Status:Ready for review PR ready for review or re-review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants