feat(infield-button): Phase 2 — file structure, API, TypeScript, and accessibility#6492
Conversation
Creates the base class, types, concrete component, stub CSS, and entry points for the infield-button 2nd-gen migration. The base class extends ButtonBase with a restricted size set (s/m/l/xl), quiet property, and delegatesFocus: false (buttons are pointer-only, not in tab order). Wires the core package.json exports for the new component. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
📚 Branch Preview Links🔍 Gen1 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 |
5t3ph
left a comment
There was a problem hiding this comment.
One minor consideration, otherwise looks good!
| ?disabled=${this.disabled} | ||
| aria-label=${ifDefined(this.accessibleLabel)} | ||
| > | ||
| <slot name="icon"></slot> |
There was a problem hiding this comment.
Do we need this to be named, or can it be a default slot?
There was a problem hiding this comment.
Yes, it needs to stay named. ButtonBase composes ObserveSlotPresence(SpectrumElement, '[slot="icon"]'), so hasIcon (i.e. this.slotContentIsPresent) only fires when content is assigned to the named slot. You are right a default-slot icon would make it permanently false, which in turn would silence the dev-mode accessible-label warning in ButtonBase.update() that guards against unlabelled icon buttons.
I am keeping it named also stays consistent with every other ButtonBase subclass and matches the 1st-gen consumer API, so there's one less migration burden either way.
Description
Scaffolds the 2nd-gen
infield-buttoncomponent for Phase 2 of the 1st-gen → 2nd-gen component migration. This PR creates the core and SWC file structure, establishes the base class architecture, and wires the package exports so the element is importable — but contains no production styling (that comes in Phase 5).Motivation and context
Infield buttons are embedded inside form fields (e.g. number-field increment/decrement controls). Their migration has specific architectural constraints captured in the migration plan (PR #6441):
delegatesFocus: falseon the shadow root andtabindex="-1"on the inner<button>.sizeattribute. Valid sizes ares,m,l,xl.quietattribute reflects to the host for CSS:host([quiet])targeting in Phase 5.InfieldButtonBaselives in core so other form-field components can extend it without inheriting the SWC visual surface.Related issue(s)
Screenshots (if appropriate)
N/A — scaffold only, no visual output yet.
Author's checklist
Reviewer's checklist
patch,minor, ormajorfeaturesManual review test cases
InfieldButtonBaseextendsButtonBasecorrectly;VALID_SIZESrestricted to['s','m','l','xl']InfieldButtonBasefrom@spectrum-web-components/core/components/infield-buttonInfieldButtonBase.VALID_SIZESequals['s','m','l','xl']InfieldButtonBase.shadowRootOptions.delegatesFocusisfalseElement registers and renders without errors
@adobe/spectrum-wc/components/infield-button/swc-infield-button.js<swc-infield-button accessible-label="Increment" size="m"><sp-icon-chevron100 slot="icon"></sp-icon-chevron100></swc-infield-button>in the DOM<button tabindex="-1">Tabdoes not focus the buttonquietattribute reflects to hostquietproperty totrueon the element[quiet]attribute is present on the host elementDevice review
Accessibility testing checklist
This PR scaffolds the structural foundation only. No user-facing interaction surface is added beyond what is already covered by
ButtonBase. Full accessibility testing will occur in Phase 4 (migration-a11y).tabindex="-1"on the inner<button>anddelegatesFocus: falseon the shadow root. They must not be reachable viaTab. The parent field owns keyboard behavior.accessible-labelis forwarded toaria-labelon the inner<button>via the inheritedButtonBasebinding. Phase 4 will verify the full announcement behavior in context.