docs(infield-button): add Phase 1 migration plan#6441
Conversation
Adds the Phase 1 (prep) migration plan for swc-infield-button: 1st-gen API surface, breaking changes, 2nd-gen API decisions, core/SWC split, and the full Setup/API/Styling/A11y/Testing/Docs checklist. Design and CSS inputs are confirmed against the Figma S2 In-field button spec and the spectrum-two infieldbutton/index.css baseline. Styling and section structure follow the migration-prep template and align with the button/action-button plans. Updates the components README nav. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Coverage Report for CI Build 28187632272Warning No base build found for commit Coverage: 96.244%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsRequires a base build to compare against. How to fix this → Coverage Stats💛 - Coveralls |
|
|
||
| | # | What changes | 1st-gen behavior | 2nd-gen behavior | Consumer migration path | | ||
| | --- | ------------ | ---------------- | ---------------- | ----------------------- | | ||
| | **B1** | Remove `block` attribute | `block="start"/"end"` adjusted corner radius and border for stacked stepper pairs | Removed. S2 uses consistent corner radius; parent field host owns stacked layout via DOM order and CSS | Remove `block` attribute from all `sp-infield-button` usages. Restructure parent field layout to manage corner radius and borders on the containing field element. | |
There was a problem hiding this comment.
We could clean this up a bit, it's a bit misleading. S2 won't have a stacked layout as the buttons will lay side by side, I believe. And because the buttons aren't flush against the parent field anymore, we don't need to manage corner radius and borders as before.
| | **B1** | Remove `block` attribute | `block="start"/"end"` adjusted corner radius and border for stacked stepper pairs | Removed. S2 uses consistent corner radius; parent field host owns stacked layout via DOM order and CSS | Remove `block` attribute from all `sp-infield-button` usages. Restructure parent field layout to manage corner radius and borders on the containing field element. | | |
| | **B1** | Remove `block` attribute | `block="start"/"end"` adjusted corner radius and border for stacked stepper pairs | Removed. S2 uses consistent corner radius. | Remove `block` attribute from all `sp-infield-button` usages. | |
| | --- | ------------ | ---------------- | ---------------- | ----------------------- | | ||
| | **B1** | Remove `block` attribute | `block="start"/"end"` adjusted corner radius and border for stacked stepper pairs | Removed. S2 uses consistent corner radius; parent field host owns stacked layout via DOM order and CSS | Remove `block` attribute from all `sp-infield-button` usages. Restructure parent field layout to manage corner radius and borders on the containing field element. | | ||
| | **B2** | Remove `inline` attribute | `inline="start"/"end"` adjusted corner radius and edge attachment for horizontal inline groups | Removed. Same reason as B1. The parent field host owns inline-group layout (it renders the `.swc-InfieldButton-inline` wrapper). | Remove `inline` attribute. Ensure the parent field host wraps the in-field buttons in the `.swc-InfieldButton-inline` container (or equivalent CSS context). | | ||
| | **B3** | Rename `label` → `accessible-label` | `label` attribute maps to `aria-label` on inner `<button>` | `accessible-label` attribute maps to `aria-label` on inner `<button>`, via `ButtonBase`'s `accessibleLabel` property | Replace `label="…"` with `accessible-label="…"` on each `sp-infield-button`. **Required for icon-only; dev warning fires if omitted.** | |
There was a problem hiding this comment.
"Required for icon-only" is a bit confusing here given that the component is always icon-only.
| | **B2** | Remove `inline` attribute | `inline="start"/"end"` adjusted corner radius and edge attachment for horizontal inline groups | Removed. Same reason as B1. The parent field host owns inline-group layout (it renders the `.swc-InfieldButton-inline` wrapper). | Remove `inline` attribute. Ensure the parent field host wraps the in-field buttons in the `.swc-InfieldButton-inline` container (or equivalent CSS context). | | ||
| | **B3** | Rename `label` → `accessible-label` | `label` attribute maps to `aria-label` on inner `<button>` | `accessible-label` attribute maps to `aria-label` on inner `<button>`, via `ButtonBase`'s `accessibleLabel` property | Replace `label="…"` with `accessible-label="…"` on each `sp-infield-button`. **Required for icon-only; dev warning fires if omitted.** | | ||
| | **B4** | Remove link API (`href`, `target`, `download`, `rel`, `referrerpolicy`) | Inherited from 1st-gen `ButtonBase` via `LikeAnchor` mixin | Not implemented. `swc-infield-button` is always `type="button"`. 2nd-gen `ButtonBase` does not expose link attributes. | Remove any `href`-based usage of `sp-infield-button`. Use `<a>` or `swc-button` with an `href` when navigation is needed in a field context (uncommon). | | ||
| | **B5** | Remove `--mod-infield-button-*` CSS custom properties | 17 modifier properties supported | None of the `--mod-infield-button-*` properties are carried forward. `--swc-infield-button-*` properties may be introduced selectively (see A1). | Consumers overriding infield-button styling via `--mod-infield-button-*` must switch to `--swc-infield-button-*` equivalents when available, or use CSS custom property targeting directly. | |
There was a problem hiding this comment.
I'm not totally sure what "use CSS custom property targeting directly" means, but overall our styling in Gen 2 is meant to be less reliant on custom properties and would use the tokens directly when appropriate.
| | **B3** | Rename `label` → `accessible-label` | `label` attribute maps to `aria-label` on inner `<button>` | `accessible-label` attribute maps to `aria-label` on inner `<button>`, via `ButtonBase`'s `accessibleLabel` property | Replace `label="…"` with `accessible-label="…"` on each `sp-infield-button`. **Required for icon-only; dev warning fires if omitted.** | | ||
| | **B4** | Remove link API (`href`, `target`, `download`, `rel`, `referrerpolicy`) | Inherited from 1st-gen `ButtonBase` via `LikeAnchor` mixin | Not implemented. `swc-infield-button` is always `type="button"`. 2nd-gen `ButtonBase` does not expose link attributes. | Remove any `href`-based usage of `sp-infield-button`. Use `<a>` or `swc-button` with an `href` when navigation is needed in a field context (uncommon). | | ||
| | **B5** | Remove `--mod-infield-button-*` CSS custom properties | 17 modifier properties supported | None of the `--mod-infield-button-*` properties are carried forward. `--swc-infield-button-*` properties may be introduced selectively (see A1). | Consumers overriding infield-button styling via `--mod-infield-button-*` must switch to `--swc-infield-button-*` equivalents when available, or use CSS custom property targeting directly. | | ||
| | **B6** | Icons move from default slot → `icon` slot | `<sp-infield-button label="…"><sp-icon-add></sp-icon-add></sp-infield-button>` (icon in default slot) | Icon must be in the named `icon` slot to trigger `ButtonBase`'s `hasIcon` detection and the `accessible-label` dev warning | Add `slot="icon"` to slotted icon elements: `<swc-infield-button accessible-label="…"><sp-icon-add slot="icon"></sp-icon-add></swc-infield-button>` | |
There was a problem hiding this comment.
This <swc-infield-button...> code snippet includes <sp-icon>, should it be <swc-icon> instead?
I think if #6415 goes through we'd also be slotting the <svg> element into <swc-icon> rather than using something like <swc-icon-add>
|
|
||
| | Slot | Content | Notes | | ||
| | ---- | ------- | ----- | | ||
| | `icon` | Icon element | **Confirmed.** Named `icon` slot (from `ButtonBase`). `ObserveSlotPresence` in `ButtonBase` monitors `[slot="icon"]` for icon presence. Icon must be decorative (`aria-hidden="true"` on the icon element when `accessible-label` provides the name). **Breaking change from 1st-gen default slot (B6).** | |
There was a problem hiding this comment.
I read this part about the aria-hidden and interpret it as being something that needs to be added manually, I think the icon component takes care of putting aria-hidden="true" on the icon element so it's not necessary to add it, but worth double-checking.
That might just be me misreading what this is trying to say, definitely feel free to disregard this comment if you don't think it needs a change.
| - Disabled: background `token("disabled-background-color")`, icon `token("disabled-content-color")` | ||
| - Quiet: `transparent` background for default, hover, active, and disabled (not the gray disabled color) | ||
| - [ ] Focus model: the inner `<button>` sets `outline: none` (matches S2 source). In **composed** field contexts the parent field (number-field, textfield, picker) owns the focus-visible ring while the inner `<button>` stays keyboard-reachable via `delegatesFocus`; verify with a field-level story. In **isolated** standalone usage there is no visible focus indicator by default; if one is required it must be added deliberately and meet WCAG 2.4.7. Do not add a competing `:focus-visible` outline that would double-ring inside a field | ||
| - [ ] Forced colors (Windows High Contrast): default variant on `.swc-InfieldButton` → background `ButtonText`, icon `ButtonFace`, `forced-color-adjust: none` on the `<button>`; disabled → background `GrayText`; hover/active/focus-visible → background `Highlight`. Quiet variant → background `Canvas`, icon `ButtonText`; disabled → `Canvas` / `GrayText`; hover/active/focus-visible → `Canvas` / `Highlight`. Sort the `@media (forced-colors: active)` block to the bottom of the file per style guide |
There was a problem hiding this comment.
I have some doubts about this item. Our style guide explicitly says:
Forced colors styles are only included when browser defaults are not sufficient
So I would hesitate to just bring over styles from spectrum-css before checking them manually.
However, after consulting with a couple of agents, they both pushed back on my doubts and said it was reasonable to port the styles over from spectrum-css... wonder if we need an adjustment in a skill or doc somewhere? Tagging @5t3ph if she has an opinion on this.
|
|
||
| | # | Item | Blocking? | Status | Owner | | ||
| | --- | ---- | --------- | ------ | ----- | | ||
| | **Q3** | **Migration ordering: infield-button before number-field.** Recommended based on the number-field rendering analysis explicitly composing `swc-infield-button`. If the team has a different sequencing preference, both this plan and the number-field analysis need updating. | Yes — affects planning | Open (recommendation made) | Architecture reviewer. Next action: confirm or override the sequencing recommendation. | |
There was a problem hiding this comment.
We might be able to remove this item or at least close it out - the sequencing seems to be confirmed, especially given that we're working on this migration plan first and holding number field for later.
| | --- | ---- | --------- | ------ | ----- | | ||
| | **Q3** | **Migration ordering: infield-button before number-field.** Recommended based on the number-field rendering analysis explicitly composing `swc-infield-button`. If the team has a different sequencing preference, both this plan and the number-field analysis need updating. | Yes — affects planning | Open (recommendation made) | Architecture reviewer. Next action: confirm or override the sequencing recommendation. | | ||
| | **Q4** | **Component existence: should `swc-infield-button` remain a standalone component?** The ticket explicitly asks whether this component is needed and whether it intersects with Clear or Close button. **Recommendation: keep as a standalone component.** Rationale: (1) The CSS tokens are specialized (`--spectrum-in-field-button-*`) and designed for field-chrome integration. (2) The quiet variant has unique transparent-background field-integration behavior. (3) Neither `swc-clear-button` nor `swc-close-button` has a migration analysis yet — merging before either is analyzed would be premature. (4) The number-field migration explicitly depends on `swc-infield-button`. (5) There is no React Spectrum counterpart to reconcile with. **Counter-argument:** If the team decides `swc-clear-button` and quiet `swc-infield-button` are functionally equivalent for the clear-field use case, they should be consolidated before either migrates to avoid a second breaking change. This is Q5 below. | Yes — decision affects scope | Open (recommendation made) | Architecture reviewer. Next action: team confirms keep vs consolidate before implementation begins. | | ||
| | **Q5** | **Scope intersection with `swc-clear-button`: who owns "clear field" affordances?** In 1st-gen, `sp-infield-button` is used for generic field actions (stepper +/−, disclosure). `sp-clear-button` is a separate component. In 2nd-gen, if `swc-infield-button` (quiet variant) and `swc-clear-button` have the same visual appearance, there is an argument for a single component. **Recommendation: keep separate, but resolve the composition contract before `swc-number-field` migration.** Confirm: does `swc-textfield` / `swc-search` use `swc-infield-button` or `swc-clear-button` for their clear actions? The answer affects the scope boundary and the consumer migration guide for both components. The Figma In-field button spec ([`126176-34080`](https://www.figma.com/design/Mngz9H7WZLbrCvGQf3GnsY/S2---Web--Desktop-scale-?node-id=126176-34080)) documents a **clear** icon affordance as one of the in-field button icon types, which is direct evidence for the overlap. Next action: review that frame and the textfield/search rendering analyses to confirm which button type each field uses for clear. | Partial — blocks consumer guide scope | Open | Architecture + design. | |
There was a problem hiding this comment.
Next action: review that frame and the textfield/search rendering analyses to confirm which button type each field uses for clear.
These exist, no? Feels like we could probably have an agent knock this out quickly and close this out? Also I believe textfield/search and also tag use the clear-button rather than the infield button.
📚 Branch Preview Links🔍 First Generation Visual Regression Test ResultsWhen 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: If the changes are expected, update the |
The Sidenav accessibility-migration-analysis entry in preview.ts belongs to a separate commit and should not be part of this migration plan PR. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5t3ph
left a comment
There was a problem hiding this comment.
It looks like the agent was mixing up ButtonBase from 1st-gen vs 2nd-gen, and I probably missed some spots where that impacts the recommendations here.
| | --- | ------------ | ---------------- | ---------------- | ----------------------- | | ||
| | **S1** | CSS custom properties (see B5 in API table above) | `--mod-infield-button-*` | `--swc-infield-button-*` (limited set; see A1) | Same as B5 in API table | | ||
| | **S2** | Stacked-border tokens removed | `--mod-infield-button-stacked-*` tokens handled inner border radius resets for stacked pairs | Removed entirely; S2 uses a consistent corner radius on each button | No consumer action needed if `block`/`inline` are removed per B1/B2 | | ||
| | **S3** | Focus state ownership shifts to parent | 1st-gen: each `sp-infield-button` manages its own `:focus-visible` ring | 2nd-gen: the inner `<button>` suppresses its own outline (`outline: none`, matching S2 source); the parent field shows the focus ring in composed contexts while the inner `<button>` stays keyboard-reachable | Verify with field-level stories that focus visibility is preserved and meets WCAG 2.4.7 | |
There was a problem hiding this comment.
If the button is independently focusable, then it needs to retain a focus ring for keyboard a11y.
| | `size` | `'s' \| 'm' \| 'l' \| 'xl'` | none | `size` | **Confirmed** | `noDefaultSize: true` preserved; parent field host must provide size. | | ||
| | `disabled` | `boolean` | `false` | `disabled` | **Confirmed** | From `ButtonBase`. Both self-disabled and parent-driven `disabled` must work. | | ||
| | `accessibleLabel` | `string \| undefined` | undefined | `accessible-label` | **Confirmed** | From 2nd-gen `ButtonBase`. Required for icon-only. Dev warning fires when `hasIcon && !hasLabel && !accessibleLabel`. | | ||
| | `active` | `boolean` | `false` | `active` | **Inferred** | From `ButtonBase`. Preserves pressed visual state. | |
There was a problem hiding this comment.
This is not available in 2nd-gen ButtonBase. Do we actually need this state? What is the use case for a "toggle" button in-field?
| | `disabled` | `boolean` | `false` | `disabled` | **Confirmed** | From `ButtonBase`. Both self-disabled and parent-driven `disabled` must work. | | ||
| | `accessibleLabel` | `string \| undefined` | undefined | `accessible-label` | **Confirmed** | From 2nd-gen `ButtonBase`. Required for icon-only. Dev warning fires when `hasIcon && !hasLabel && !accessibleLabel`. | | ||
| | `active` | `boolean` | `false` | `active` | **Inferred** | From `ButtonBase`. Preserves pressed visual state. | | ||
| | `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | `type` | **Confirmed** | From `ButtonBase`. Always `"button"` for in-field adornments in practice; `submit`/`reset` deferred (A3). | |
There was a problem hiding this comment.
Also not in 2nd-gen ButtonBase, so perhaps consider it dropped from the API or at least deferred?
| Additional presentation modes **not supported in 2nd-gen:** | ||
| - Stacked position variant (`block="start"/"end"`) — removed; consistent corner radius in S2 | ||
| - Inline position variant (`inline="start"/"end"`) — removed; the parent field host owns inline-group layout (it renders the `.swc-InfieldButton-inline` wrapper around the slotted buttons), not `swc-infield-button` itself | ||
| - Static color (`static-color="white"/"black"`) — **not present** in Figma S2 spec; confirmed absent (not in 1st-gen; no field-chrome use case for static color) |
There was a problem hiding this comment.
ButtonBase is currently slated to get staticColor exposed via this PR, so if that happens you'll need to exclude it.
| | `icon` | Icon element | **Confirmed.** Named `icon` slot (from `ButtonBase`). `ObserveSlotPresence` in `ButtonBase` monitors `[slot="icon"]` for icon presence. The `swc-icon` component sets `aria-hidden="true"` on itself; no manual attribute needed on the slotted element. **Breaking change from 1st-gen default slot (B6).** | | ||
| | (default) | Optional visible label text | **Inferred.** Unlikely to contain content in typical use — `swc-infield-button` is always icon-only in practice. Present because `ButtonBase` exposes it; `ObserveSlotText` monitors it for `hasLabel`. | |
There was a problem hiding this comment.
These are not in 2nd-gen ButtonBase since that doesn't manage render.
| [`swc-InfieldButton--size${size?.toUpperCase()}`]: !!size, | ||
| 'swc-InfieldButton--quiet': this.quiet, |
There was a problem hiding this comment.
[nit] attribute selectors will be used for these states
| 'swc-InfieldButton--quiet': this.quiet, | ||
| })} | ||
| > | ||
| <div class="swc-InfieldButton-fill"> |
There was a problem hiding this comment.
[nit] this is kind of odd naming, what is "fill" trying to communicate? Also I wonder if this will be able to be removed in favor of just ::slotted() styles.
- S3: clarify that standalone use retains its own focus-visible ring; the outline:none suppression applies only in composed field contexts - Drop 'active' from public API: not in ButtonBase; :active CSS handles pressed visual; no toggle use case in-field - Drop 'type' from public API: not in ButtonBase; concrete template hardcodes type="button"; submit/reset deferred to A3 - static-color: add note that if ButtonBase gains staticColor (PR #6410), swc-infield-button must explicitly exclude it - Default slot: fix wording — slots are in the concrete template, not provided by ButtonBase (which has no render method) - Render template: replace BEM modifier classMap with attribute selectors; quiet and size are reflected so :host([quiet]) / :host([size="s"]) apply - Remove fill wrapper div from template; add Phase 5 note to verify whether the wrapper is required or ::slotted() alone is sufficient Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7c9d325 to
164bd13
Compare
| - Active/down: background `token("gray-200")`, icon `token("neutral-content-color-down")`; `transform: perspective(...) translateZ(...)` on the `<button>` using the S2 downstate tokens | ||
| - Disabled: background `token("disabled-background-color")`, icon `token("disabled-content-color")` | ||
| - Quiet: `transparent` background for default, hover, active, and disabled (not the gray disabled color) | ||
| - [ ] Focus model: the inner `<button>` sets `outline: none` (matches S2 source). In **composed** field contexts the parent field (number-field, textfield, picker) owns the focus-visible ring while the inner `<button>` stays keyboard-reachable via `delegatesFocus`; verify with a field-level story. In **isolated** standalone usage there is no visible focus indicator by default; if one is required it must be added deliberately and meet WCAG 2.4.7. Do not add a competing `:focus-visible` outline that would double-ring inside a field |
There was a problem hiding this comment.
Further up, the plan says:
When used standalone (outside a parent field), the button must retain its own
:focus-visiblering to satisfy WCAG 2.4.7.
Here it says:
In isolated standalone usage there is no visible focus indicator by default; if one is required it must be added deliberately and meet WCAG 2.4.7.
We might change this part to remove the "if one is required"
|
|
||
| - [ ] `InfieldButton.types.ts`: define `InfieldButtonSize` (alias or reuse from `BUTTON_VALID_SIZES`), `InfieldButtonQuiet` boolean | ||
| - [ ] `InfieldButton.base.ts`: extend 2nd-gen `ButtonBase` with `SizedMixin(ButtonBase, { noDefaultSize: true })`; `validSizes` does not need overriding because `BUTTON_VALID_SIZES` already equals `['s', 'm', 'l', 'xl']` (see Q6); add `quiet: boolean` property (reflect: true) | ||
| - [ ] `InfieldButton.ts`: extend `InfieldButton.base.ts`; register as `swc-infield-button`; render inner `<button>` (with size and `quiet` modifier classes via `classMap`) containing a `.swc-InfieldButton-fill` div that wraps the `icon` slot |
There was a problem hiding this comment.
We're not using classMap for size/quiet modifiers, we'd use the host attribute selectors - this appears in a couple places:
Here:
(with size and
quietmodifier classes viaclassMap)
Around L429:
Apply
.swc-InfieldButton(with size/quiet modifier classes viaclassMap)
There was a problem hiding this comment.
Also, an additional note that we're saying earlier that the fill <div> might not be needed, it could be helpful for the agent to ensure that's mentioned again here
| - [ ] Apply `.swc-InfieldButton` (with size/quiet modifier classes via `classMap`) to the inner `<button>`; keep styling off `:host` | ||
| - [ ] Update class and custom property prefixes from `.spectrum-InfieldButton` to `.swc-InfieldButton`; **remove all `--mod-infield-button-*` and `--spectrum-infield-button-*` fallback chains**, collapsing each into a single intentional `--swc-infield-button-*` property with a `token(...)` default per the [custom properties style guide](../../../../CONTRIBUTOR-DOCS/02_style-guide/01_css/02_custom-properties.md) | ||
| - [ ] Style the slotted icon with `slot[name="icon"]::slotted(*)` (color + size-specific padding), as `swc-button` does; do **not** put a `.swc-InfieldButton-icon` class on the consumer-slotted node (the S2 `.spectrum-InfieldButton-icon` rule targets an inline SVG in the CSS-only template, which does not apply to the slotted web-component case) | ||
| - [ ] `.swc-InfieldButton-fill` (inner `<div>`) owns `background-color`, `border-radius`, and the centering flex |
There was a problem hiding this comment.
Noting we said earlier that .swc-InfieldButton-fill might not be necessary, I mentioned this as well in my comment on L412
| `swc-infield-button` has no `href` or related anchor attributes. It is always `type="button"` in practice. | ||
|
|
||
| **`noDefaultSize: true`:** | ||
| The component does not pick a default size. The parent field host must set `size` (either by attribute or inherited context). This behavior is preserved from 1st-gen. 2nd-gen `ButtonBase` already applies `SizedMixin` with `validSizes: BUTTON_VALID_SIZES` (= `['s', 'm', 'l', 'xl']`), so `InfieldButton.base.ts` only needs to re-apply `SizedMixin(..., { noDefaultSize: true })`; the `validSizes` set already matches and does not need to be overridden (see Q6). Note that M is the Figma **reference** size, not a component default. |
There was a problem hiding this comment.
Claude's informed me that we might copy the action button's approach on this?
| Additional presentation modes **not supported in 2nd-gen:** | ||
| - Stacked position variant (`block="start"/"end"`) — removed; consistent corner radius in S2 | ||
| - Inline position variant (`inline="start"/"end"`) — removed; the parent field host owns inline-group layout (it renders the `.swc-InfieldButton-inline` wrapper around the slotted buttons), not `swc-infield-button` itself | ||
| - Static color (`static-color="white"/"black"`) — **not present** in Figma S2 spec; confirmed absent (not in 1st-gen; no field-chrome use case for static color). **Note:** if `ButtonBase` gains a `staticColor` property (tracked in PR #6410), `swc-infield-button` must explicitly exclude or override it to prevent consumers from setting an unsupported value. |
There was a problem hiding this comment.
Do we also need to do this for pending? The infield button doesn't have pending, but the button base does, so we would need to ensure it doesn't unintentionally set pending styles without any pending action?
5t3ph
left a comment
There was a problem hiding this comment.
Apologies for causing confusion on the focus behavior. I have chatted with Nikki and gotten clarification on the expected behavior.
Infield button focus/keyboard behavior corrections
- Infield buttons are never standalone — remove that scenario and its
:focus-visiblering requirement. - They are clickable but not focusable. Keyboard behavior equivalent to clicking (e.g., arrow keys for increment/decrement on number field) is owned by the parent field, not the button.
- The parent field's focus ring is the only focus indicator needed — no separate WCAG 2.4.7 concern for the button itself.
Please update the plan to reflect this with language that makes the non-focusable, parent-delegated keyboard model explicit.
| - Stacked position variant (`block="start"/"end"`) — removed; consistent corner radius in S2 | ||
| - Inline position variant (`inline="start"/"end"`) — removed; the parent field host owns inline-group layout (it renders the `.swc-InfieldButton-inline` wrapper around the slotted buttons), not `swc-infield-button` itself | ||
| - Static color (`static-color="white"/"black"`) — **not present** in Figma S2 spec; confirmed absent (not in 1st-gen; no field-chrome use case for static color) | ||
| - Static color (`static-color="white"/"black"`) — **not present** in Figma S2 spec; confirmed absent (not in 1st-gen; no field-chrome use case for static color). **Note:** if `ButtonBase` gains a `staticColor` property (tracked in PR #6410), `swc-infield-button` must explicitly exclude or override it to prevent consumers from setting an unsupported value. |
There was a problem hiding this comment.
Update that the close button PR ended up reverting this decision since at least infield and clear do not use static colors
Description
Adds the Phase 1 (prep) migration plan for
swc-infield-buttonunderCONTRIBUTOR-DOCS/03_project-planning/03_components/infield-button/, completing the planning artifact set alongside the existing rendering/styling and accessibility migration analyses.The plan documents the 1st-gen API surface, breaking changes, 2nd-gen API decisions, the core/SWC architecture split, and the full Setup → API → Styling → Accessibility → Testing → Documentation → Review checklist. It follows the
migration-preptemplate and is structurally aligned with thebuttonandaction-buttonplans.Highlights
quiet+ four sizes (s/m/l/xl,noDefaultSize: true), extends 2nd-genButtonBase; link API,block/inline,pending, and--mod-*removed;label→accessible-label; icon moves to the namediconslot.126176-34080) and thespectrum-twocomponents/infieldbutton/index.cssbaseline (sizes, states, quiet, forced-colors, no stacked/:lang()classes).token()+--swc-infield-button-*, slotted-icon styling via::slotted, parent-field-owned focus model and inline-group wrapper.Open questions (tracked in the plan)
These are team decisions and intentionally remain open before implementation begins:
swc-infield-buttonstandalone vs. merge with clear/close-buttonType of change
Related issue(s)
SWC-2147 (Epic: SWC-2107)
Test plan