Skip to content

Conversation

@nikkimk
Copy link
Contributor

@nikkimk nikkimk commented Oct 10, 2025

Description

Motivation and context

Related issue(s)

  • fixes SWC-1042
  • fixes SWC-1045

Screenshots (if appropriate)


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 Note: Ignore any visual regressions issues at this time as they will be addressed in SWC-1316 before this branch is merged into main

Manual review test cases

Note: Ignore any CSS issues at this time as they will be addressed in SWC-1316 before this branch is merged into main

  • Text Field

    1. Go to Textfield#Label
    2. Verify that the example with the slotted label is visible.
    3. Verify that the example with the visually hidden label is not visible.
    4. Use the keyboard and screen reader to check each example.
    5. Expect the screen reader to read the label whether it is visible or hidden.
  • Color Field

    1. Go to Color Field#Label
    2. Verify that the example with the slotted label is visible.
    3. Verify that the example with the visually hidden label is not visible.
    4. Use the keyboard and screen reader to check each example.
    5. Expect the screen reader to read the label whether it is visible or hidden.
  • Number Field

    1. Go to Number Field#Label
    2. Verify that the example with the slotted label is visible.
    3. Verify that the example with the visually hidden label is not visible.
    4. Use the keyboard and screen reader to check each example.
    5. Expect the screen reader to read the label whether it is visible or hidden.
  • Combobox

    1. Go to Combobox#Label
    2. Verify that the example with the slotted label is visible.
    3. Verify that the example with the visually hidden label is not visible.
    4. Use the keyboard and screen reader to check each example.
    5. Expect the screen reader to read the label whether it is visible or hidden.

Device review

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

nikkimk added 27 commits October 7, 2025 11:18
feat(label): init field label mixin
@changeset-bot
Copy link

changeset-bot bot commented Oct 10, 2025

🦋 Changeset detected

Latest commit: f24e789

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

This PR includes changesets to release 84 packages
Name Type
@spectrum-web-components/number-field Minor
@spectrum-web-components/field-label Minor
@spectrum-web-components/combobox Minor
@spectrum-web-components/textfield Minor
@spectrum-web-components/color-field Minor
@spectrum-web-components/slider Minor
@spectrum-web-components/bundle Minor
@spectrum-web-components/action-bar Minor
@spectrum-web-components/meter Minor
@spectrum-web-components/picker Minor
@spectrum-web-components/progress-bar Minor
@spectrum-web-components/custom-vars-viewer Minor
example-project-rollup Patch
example-project-webpack Patch
@spectrum-web-components/story-decorator Minor
@spectrum-web-components/search Minor
documentation Patch
@spectrum-web-components/vrt-compare Minor
@spectrum-web-components/action-menu Minor
@spectrum-web-components/breadcrumbs Minor
@spectrum-web-components/eslint-plugin Minor
@spectrum-web-components/accordion Minor
@spectrum-web-components/action-button Minor
@spectrum-web-components/action-group Minor
@spectrum-web-components/alert-banner Minor
@spectrum-web-components/alert-dialog Minor
@spectrum-web-components/asset Minor
@spectrum-web-components/avatar Minor
@spectrum-web-components/badge Minor
@spectrum-web-components/button-group Minor
@spectrum-web-components/button Minor
@spectrum-web-components/card Minor
@spectrum-web-components/checkbox Minor
@spectrum-web-components/clear-button Minor
@spectrum-web-components/close-button Minor
@spectrum-web-components/coachmark Minor
@spectrum-web-components/color-area Minor
@spectrum-web-components/color-handle Minor
@spectrum-web-components/color-loupe Minor
@spectrum-web-components/color-slider Minor
@spectrum-web-components/color-wheel Minor
@spectrum-web-components/contextual-help Minor
@spectrum-web-components/dialog Minor
@spectrum-web-components/divider Minor
@spectrum-web-components/dropzone Minor
@spectrum-web-components/field-group Minor
@spectrum-web-components/help-text Minor
@spectrum-web-components/icon Minor
@spectrum-web-components/icons-ui Minor
@spectrum-web-components/icons-workflow Minor
@spectrum-web-components/icons Minor
@spectrum-web-components/iconset Minor
@spectrum-web-components/illustrated-message Minor
@spectrum-web-components/infield-button Minor
@spectrum-web-components/link Minor
@spectrum-web-components/menu Minor
@spectrum-web-components/modal Minor
@spectrum-web-components/overlay Minor
@spectrum-web-components/picker-button Minor
@spectrum-web-components/popover Minor
@spectrum-web-components/progress-circle Minor
@spectrum-web-components/radio Minor
@spectrum-web-components/sidenav Minor
@spectrum-web-components/split-view Minor
@spectrum-web-components/status-light Minor
@spectrum-web-components/swatch Minor
@spectrum-web-components/switch Minor
@spectrum-web-components/table Minor
@spectrum-web-components/tabs Minor
@spectrum-web-components/tags Minor
@spectrum-web-components/thumbnail Minor
@spectrum-web-components/toast Minor
@spectrum-web-components/tooltip Minor
@spectrum-web-components/top-nav Minor
@spectrum-web-components/tray Minor
@spectrum-web-components/underlay Minor
@spectrum-web-components/base Minor
@spectrum-web-components/grid Minor
@spectrum-web-components/opacity-checkerboard Minor
@spectrum-web-components/reactive-controllers Minor
@spectrum-web-components/shared Minor
@spectrum-web-components/styles Minor
@spectrum-web-components/theme Minor
@spectrum-web-components/truncated Minor

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

@github-actions
Copy link
Contributor

github-actions bot commented Oct 10, 2025

📚 Branch Preview

🔍 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-5799

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.

@github-actions
Copy link
Contributor

github-actions bot commented Oct 10, 2025

Tachometer results

Chrome

menu permalink

test-basic

Version Bytes Avg Time vs remote vs branch
npm latest 522 kB 170.44ms - 174.35ms - faster ✔
2% - 4%
3.09ms - 7.93ms
branch 510 kB 176.48ms - 179.34ms slower ❌
2% - 5%
3.09ms - 7.93ms
-
Firefox

menu permalink

test-basic

Version Bytes Avg Time vs remote vs branch
npm latest 522 kB 359.68ms - 370.28ms - faster ✔
1% - 5%
5.22ms - 19.22ms
branch 510 kB 372.64ms - 381.76ms slower ❌
1% - 5%
5.22ms - 19.22ms
-

nikkimk and others added 3 commits October 24, 2025 08:33
Co-authored-by: Marissa Huysentruyt <69602589+marissahuysentruyt@users.noreply.github.com>
Co-authored-by: Marissa Huysentruyt <69602589+marissahuysentruyt@users.noreply.github.com>
* @slot tooltip - Tooltip to to be applied to the the Picker Button
*/
export class Combobox extends Textfield {
export class Combobox extends FieldLabelMixin(Textfield, 'field-label') {
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmmm.... this is interesting... Textfield already has FieldLabelMixin applied in its inheritance chain....
Textfield → TextfieldBase → FieldLabelMixin(ManageHelpText(...))
I'm not sure, but this sounds like this it could create problems? Can't say for sure what, but could this lead to duplicate field-label styles?, two separate renderFieldLabel() implementations where one shadows the other?, potentially conflicting slot observation? 🤷

Maybe the solution is just

Suggested change
export class Combobox extends FieldLabelMixin(Textfield, 'field-label') {
export class Combobox extends Textfield {

and keep the renderFieldLabel('input') that we have below. Let me know what you think!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TL;DR, we need this for now but it will be gone before the merge to main


field-label is the slotName not the fieldId. In text field it makes sense just to make the slotName a default slot, but in combobox, the menuitems are in the default slot.

Also, TBH, the minute I touch SWC-710, which is also part of this branch, combobox will not extend textfield, so this is only temporary, and will be changed before the parent branch gets merged to main.

By the time this merges to main, it will be export class Combobox extends FieldLabelMixin(Menu, 'field-label') { because we need to move the menu to the same DOM as everything else and there is more I need to inherit from Menu than I do from a Textfield.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm happy with that! Thanks for the context!

Co-authored-by: Rúben Carvalho <rubcar@sapo.pt>
) {
public static override get styles(): CSSResultArray {
return [textfieldStyles, checkmarkStyles];
return [super.styles || [], textfieldStyles, checkmarkStyles];
Copy link
Contributor

Choose a reason for hiding this comment

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

I think if we don'tt spread super.styles, it can be problematic? We can end up with a nested array?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fun fact:

In our other components, super.styles has a CSSResultArray type. In Textfield, it is CSSResultGroup | undefined.

According to Lit docs:

  • CSSResultGroup is CSSResultOrNative | CSSResultArray.
  • CSSResultArray is Array<CSSResultOrNative | CSSResultArray>

In order to get around this, I had to do the following:

        const styles = (super.styles || []) as CSSResultArray;
        return [...styles, textfieldStyles, checkmarkStyles];

@nikkimk nikkimk requested a review from rubencarvalho October 24, 2025 16:28
@nikkimk nikkimk merged commit c989174 into nikkimk/form-field-mixin Nov 5, 2025
12 of 22 checks passed
@nikkimk nikkimk deleted the nikkimk/1042-form-mixins branch November 5, 2025 14:30
nikkimk added a commit that referenced this pull request Nov 6, 2025
* feat(label): init field label mixin

feat(label): init field label mixin

* feat(textfield): updated textfiled docs to use label mixin

* feat(field-label): added mixin to package exports

* feat(field-label): added optional slot name for rendering label slot

* docs(textfield): implemented label mixin in stories

* test(textfield): added test for slotted label

* feat(textfield): added default slot observer for label changes

* test(textfield): added tests for slotted label

* docs(number-field): updated number field docs based on text field label changes

* docs(number-field): updated stories with slotted label

* docs(color-field): updated docs with slotted label

* feat(field-label): updated interface to include optional slot name for label

* feat(combobox): added label slot to combobox

* docs(combobox): added slotted label to docs

* test(combobox): updates tests with slotted label

* fix(combobox): fixed combobox field id for label

* feat(field-label): added label slot change handler to mixin

* feat(combobox): added slot change handlers

* feat(field-label): hide field label if not used

* feat(textfield): use field label mixin to observe slot

* feat(combobox): use field label mixin to observe slot

* feat(combobox): added placeholder

* fix(textfield): fixed issue with detecting slot content

* fix(field-label): fixed issue with slot content detection in text field

* test(textfield): removed unneccessary id attribute

* fix(fieldl-label): fixed mixin to allow slot naming

* feat(combobox): updated combobox, stories and tests for field label mixin

* fix(field-label): corrected linting issues

* fix(menu): MenuItem focus stealing from input elements on mouseover (#5732)

* fix(menu): added check to find focused element within root context

* fix(menu): added story

* fix(menu): added test

* chore(menu): added changeset

* fix(menu): added global const for component input pattern

* fix(menu): remove delimiter from the regexp constructor

* chore: skipped prod and vrt tests on the new story

* chore: fix tests helpers

* fix: check for cross root boundary

* fix: code comments

---------

Co-authored-by: Rajdeep Chandra <rajdeepchandra@Rajdeeps-MacBook-Pro-6.local>
Co-authored-by: Rajdeep Chandra <rajdeepchandra@rajdeeps-mbp-7.macromedia.com>
Co-authored-by: Rajdeep Chandra <rajdeepchandra@Rajdeeps-MacBook-Pro-7.local>

* fix(field-label): made field id optional for picker

* fix(field-label): made field id optional for picker

* feat(picker): added field label mixin to pciker and picker stories

* fix(textfiled): fixed element name in warning

* fix(combobox): fixed element name in warning

* docs(picker): updated stories

* feat(picker): added field label mizin to picker without affecting pickerBase

* docs(textfield): documented default label slot

* feat(picker): reverting changes until picker is refactored

* feat(picker): reverting changes until picker is refactored

* feat(picker): reverting changes until picker is refactored

* feat(picker): reverting changes until picker is refactored

* feat(picker): reverting changes until picker is refactored

* feat(picker): reverting changes until picker is refactored

* feat(picker): reverting changes until picker is refactored

* feat(picker): reverting changes until picker is refactored

* feat(picker): reverting changes until picker is refactored

* feat(picker): reverting changes until picker is refactored

* docs(textfield): updated docs with label examples

* docs(textfield): fixed issue with tabs

* test(textfield): updated test warning text to match revised warning text

* docs(combobox): added label and placeholder sections to docs

* docs(textfield): changed tabs label

* docs(number-field): updated docs with a label section

* chore(changeset): added changsets

* docs(field-label): added field-label-mixin docs

* Apply suggestion from @nikkimk

* feat(picker): revert changes

* feat(picker): revert changes

* chore: updated changesets

* docs(color-field): added label docs

* chore: updated changesets

* docs(combobox): fixed typo

Co-authored-by: Casey Eickhoff <48574582+caseyisonit@users.noreply.github.com>

* docs(field-label): added JS Docs to mixin

* chore: linting fixes

* docs(combobox): fixed typo

Co-authored-by: Casey Eickhoff <48574582+caseyisonit@users.noreply.github.com>

* chore: dropped changeset

* docs(color-field): fixed typo

Co-authored-by: Marissa Huysentruyt <69602589+marissahuysentruyt@users.noreply.github.com>

* chore(combobox): fixed typo

* docs(combobox): added side-aligned to story

* docs(combobox): fixed typo

Co-authored-by: Marissa Huysentruyt <69602589+marissahuysentruyt@users.noreply.github.com>

* docs(combobox): fixed typo

Co-authored-by: Marissa Huysentruyt <69602589+marissahuysentruyt@users.noreply.github.com>

* docs(field-label): added links to mixin docs

* docs(field-label): added code type in mixin docs

Co-authored-by: Marissa Huysentruyt <69602589+marissahuysentruyt@users.noreply.github.com>

* docs(field-label): added code type in mixin docs

Co-authored-by: Marissa Huysentruyt <69602589+marissahuysentruyt@users.noreply.github.com>

* fix(textfield): simiplified styles getter

* fix(textfield): simplified attribute

Co-authored-by: Rúben Carvalho <rubcar@sapo.pt>

* fix(textfield): simplified attribute

* docs(field-label): added more detail to mixin docs

Co-authored-by: Rúben Carvalho <rubcar@sapo.pt>

* docs(field-label): added more detail to field label mixin docs

Co-authored-by: Rúben Carvalho <rubcar@sapo.pt>

* fix(field-label): fixed inherited styles in mixin

Co-authored-by: Rúben Carvalho <rubcar@sapo.pt>

* fix(field-label): set side-aligned property to optional

Co-authored-by: Rúben Carvalho <rubcar@sapo.pt>

* fix(field-label): added override to styles getter

Co-authored-by: Rúben Carvalho <rubcar@sapo.pt>

* fix(field-label): field id should be required

* fix(field-label): reverted styles changes to mixin

* fix(textfield): fixed styles array

* fix(textfield): ensure super styles are CSSResultArray

---------

Co-authored-by: Rajdeep Chandra <rajrock38@gmail.com>
Co-authored-by: Rajdeep Chandra <rajdeepchandra@Rajdeeps-MacBook-Pro-6.local>
Co-authored-by: Rajdeep Chandra <rajdeepchandra@rajdeeps-mbp-7.macromedia.com>
Co-authored-by: Rajdeep Chandra <rajdeepchandra@Rajdeeps-MacBook-Pro-7.local>
Co-authored-by: Casey Eickhoff <48574582+caseyisonit@users.noreply.github.com>
Co-authored-by: Marissa Huysentruyt <69602589+marissahuysentruyt@users.noreply.github.com>
Co-authored-by: Rúben Carvalho <rubcar@sapo.pt>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants