Skip to content
Draft
1 change: 1 addition & 0 deletions 1st-gen/packages/field-label/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"development": "./src/FieldLabelMixin.dev.js",
"default": "./src/FieldLabelMixin.js"
},
"./src/field-label-mixin.css.js": "./src/field-label-mixin.css.js",
"./src/field-label-overrides.css.js": "./src/field-label-overrides.css.js",
"./src/field-label.css.js": "./src/field-label.css.js",
"./sp-field-label-mixin.js": {
Expand Down
9 changes: 6 additions & 3 deletions 1st-gen/packages/field-label/src/FieldLabelMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import { property } from '@spectrum-web-components/base/src/decorators.js';
import '@spectrum-web-components/icons-ui/icons/sp-icon-asterisk100.js';

import styles from './field-label.css.js';
import styles from './field-label-mixin.css.js';
import asteriskIconStyles from '@spectrum-web-components/icon/src/spectrum-icon-asterisk.css.js';
import { ifDefined } from '@spectrum-web-components/base/src/directives.js';
import { ObserveSlotText } from '@spectrum-web-components/shared';
Expand Down Expand Up @@ -65,7 +65,10 @@ export const FieldLabelMixin = <T extends Constructor<SpectrumElement>>(
excludedSelectors
) {
public static get styles(): CSSResultArray {
return [styles, asteriskIconStyles];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const parent = Object.getPrototypeOf(this) as any;
const parentStyles = (parent.styles || []) as CSSResultArray;
return [...parentStyles, styles, asteriskIconStyles];
}

@property({ type: Boolean, reflect: true })
Expand All @@ -80,7 +83,7 @@ export const FieldLabelMixin = <T extends Constructor<SpectrumElement>>(
public renderFieldLabel(fieldId: string): TemplateResult {
return html`
<label
id="${fieldId}-label}"
id="${fieldId}-label"
for="${fieldId}"
?hidden="${!this.slotHasContent}"
>
Expand Down
98 changes: 98 additions & 0 deletions 1st-gen/packages/field-label/src/field-label-mixin.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* Copyright 2025 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

@import url("./field-label-overrides.css");

:host,
:host([size="m"]) {
--spectrum-field-label-min-height: var(--spectrum-component-height-75);
--spectrum-field-label-font-size: var(--spectrum-font-size-75);
--spectrum-field-label-side-margin-block-start: var(--spectrum-field-label-top-margin-medium);
--spectrum-field-label-side-padding-right: var(--spectrum-spacing-200);
--spectrum-field-label-text-to-asterisk: var(--spectrum-field-label-text-to-asterisk-medium);
}

:host([size="s"]) {
--spectrum-field-label-min-height: var(--spectrum-component-height-75);
--spectrum-field-label-font-size: var(--spectrum-font-size-75);
--spectrum-field-label-side-margin-block-start: var(--spectrum-field-label-top-margin-small);
--spectrum-field-label-side-padding-right: var(--spectrum-spacing-100);
--spectrum-field-label-text-to-asterisk: var(--spectrum-field-label-text-to-asterisk-small);
}

:host([size="l"]) {
--spectrum-field-label-min-height: var(--spectrum-component-height-100);
--spectrum-field-label-font-size: var(--spectrum-font-size-100);
--spectrum-field-label-side-margin-block-start: var(--spectrum-field-label-top-margin-large);
--spectrum-field-label-side-padding-right: var(--spectrum-spacing-200);
--spectrum-field-label-text-to-asterisk: var(--spectrum-field-label-text-to-asterisk-large);
}

:host([size="xl"]) {
--spectrum-field-label-min-height: var(--spectrum-component-height-200);
--spectrum-field-label-font-size: var(--spectrum-font-size-200);
--spectrum-field-label-side-margin-block-start: var(--spectrum-field-label-top-margin-extra-large);
--spectrum-field-label-side-padding-right: var(--spectrum-spacing-200);
--spectrum-field-label-text-to-asterisk: var(--spectrum-field-label-text-to-asterisk-extra-large);
}

label {
--spectrum-field-label-width: 100%;
}

label {
inline-size: var(--mod-field-label-width, var(--spectrum-field-label-width));
box-sizing: border-box;
min-block-size: var(--mod-fieldlabel-min-height, var(--spectrum-field-label-min-height));
padding-block: var(--mod-fieldlabel-padding-block, var(--mod-field-label-top-to-text, var(--spectrum-field-label-top-to-text)) var(--mod-field-label-bottom-to-text, var(--spectrum-field-label-bottom-to-text)));
padding-inline: 0;
padding-inline: var(--mod-fieldlabel-padding-inline, 0);
margin-block: 0;
margin-block: var(--mod-fieldlabel-margin-block, var(--mod-fieldlabel-margin-block-start, 0) var(--mod-fieldlabel-margin-block-end, 0));
margin-inline: 0;
margin-inline: var(--mod-fieldlabel-margin-inline, var(--mod-fieldlabel-margin-inline-start, 0) var(--mod-fieldlabel-margin-inline-end, 0));
font-size: var(--mod-fieldlabel-font-size, var(--spectrum-field-label-font-size));
font-weight: var(--mod-fieldlabel-font-weight, var(--spectrum-regular-font-weight));
line-height: var(--mod-fieldlabel-line-height, var(--spectrum-line-height-100));
-webkit-font-smoothing: subpixel-antialiased;
-moz-osx-font-smoothing: auto;
color: var(--highcontrast-field-label-content-color, var(--mod-fieldlabel-color, var(--spectrum-neutral-subdued-content-color-default)));
display: inline-block;
}

label[hidden] {
display: none;
}

label:lang(ja),
label:lang(ko),
label:lang(zh) {
--mod-fieldlabel-line-height: var(--mod-fieldlabel-line-height-cjk, var(--spectrum-cjk-line-height-100));
}

:host([disabled]) label {
--mod-fieldlabel-color: var(--mod-disabled-content-color, var(--spectrum-disabled-content-color));
}

.required-icon {
color: inherit;
margin-block: 0;
margin-inline: var(--mod-field-label-text-to-asterisk, var(--spectrum-field-label-text-to-asterisk)) 0;
vertical-align: initial;
vertical-align: var(--mod-field-label-asterisk-vertical-align, baseline);
}

@media (forced-colors: active) {
:host([disabled]) label {
--highcontrast-field-label-content-color: GrayText;
}
}
4 changes: 2 additions & 2 deletions 1st-gen/packages/textfield/stories/textarea.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ Line 5"
placeholder="Enter your life story"
rows="3"
>
Enter your life story...
Enter your life story with very long words...
</sp-textfield>
`;

Expand All @@ -240,6 +240,6 @@ export const with1Row = (): TemplateResult => html`
placeholder="Enter your life story"
rows="1"
>
Enter your life story... Enter your life story with very long words...
Enter your life story with very long words...
</sp-textfield>
`;
1 change: 1 addition & 0 deletions 1st-gen/packages/textfield/stories/textfield.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export const growsOnly = (): TemplateResult => {
grows
id="grows-only"
placeholder="Does not grow or display incorrectly"
style="--mod-field-label-width: 400px;"
Copy link
Collaborator Author

@rise-erpelding rise-erpelding Nov 24, 2025

Choose a reason for hiding this comment

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

Is this cheating to make the VRTs pass for this story? Yes. 😆

After poking around at CSS, React, Figma, and the design guidelines, I think the expected behavior for the field label is that its width is the same as the text input rather than being completely independent of it.

However, I realize this could potentially cause problems for consumers who expected the field label to behave the other way, so we can optionally provide a way to get around this, if we want.

Happy to have feedback on this.

>
This Textfield has the "grows" attribute without the "multiline"
attribute
Expand Down
Loading