Ensuring styles apply for input labels when using 'slot="label"' (#1757)

* Ensuring styles apply for input labels when using 'slot="label"'

* Using 'has-slotted' class for codebase consistency

* Fleshing out 'has-slotted' label class to relevant form elements

* Ensuring label line height uses the correct token; removing unrelated PR changes

* Using 'has-label' class instead of 'has-slotted' for labels; applying it with all label content
This commit is contained in:
Steve Matney
2025-12-30 10:13:28 -07:00
committed by GitHub
parent 56b1196265
commit ede1f0725d
8 changed files with 58 additions and 8 deletions

View File

@@ -1277,7 +1277,14 @@ export default class WaColorPicker extends WebAwesomeFormAssociatedElement {
})} })}
part="trigger-container form-control" part="trigger-container form-control"
> >
<div part="form-control-label" class="label" id="form-control-label"> <div
part="form-control-label"
class=${classMap({
label: true,
'has-label': hasLabel,
})}
id="form-control-label"
>
<slot name="label">${this.label}</slot> <slot name="label">${this.label}</slot>
</div> </div>

View File

@@ -48,6 +48,27 @@ describe('<wa-input>', () => {
expect(input.title).to.equal('Test'); expect(input.title).to.equal('Test');
}); });
it('should have label with "has-label" class if label has a slotted element', async () => {
const el = await fixture<WaInput>(html` <wa-input><span slot="label">Name</span></wa-input> `);
await el.updateComplete;
const label = el.shadowRoot!.querySelector('[part~="form-control-label"]')!;
expect(label.classList.contains('has-label')).to.equal(true);
});
it('should have label with "has-label" class if label is provided as an attribute', async () => {
const el = await fixture<WaInput>(html` <wa-input label="Name"></wa-input> `);
await el.updateComplete;
const label = el.shadowRoot!.querySelector('[part~="form-control-label"]')!;
expect(label.classList.contains('has-label')).to.equal(true);
});
it('should not have "has-label" class on label if no label content is provided', async () => {
const el = await fixture<WaInput>(html` <wa-input></wa-input> `);
await el.updateComplete;
const label = el.shadowRoot!.querySelector('[part~="form-control-label"]')!;
expect(label.classList.contains('has-label')).to.equal(false);
});
it('should be disabled with the disabled attribute', async () => { it('should be disabled with the disabled attribute', async () => {
const el = await fixture<WaInput>(html` <wa-input disabled></wa-input> `); const el = await fixture<WaInput>(html` <wa-input disabled></wa-input> `);
await el.updateComplete; await el.updateComplete;

View File

@@ -342,7 +342,15 @@ export default class WaInput extends WebAwesomeFormAssociatedElement {
(typeof this.value === 'number' || (this.value && this.value.length > 0)); (typeof this.value === 'number' || (this.value && this.value.length > 0));
return html` return html`
<label part="form-control-label label" class="label" for="input" aria-hidden=${hasLabel ? 'false' : 'true'}> <label
part="form-control-label label"
class=${classMap({
label: true,
'has-label': hasLabel,
})}
for="input"
aria-hidden=${hasLabel ? 'false' : 'true'}
>
<slot name="label">${this.label}</slot> <slot name="label">${this.label}</slot>
</label> </label>

View File

@@ -352,7 +352,10 @@ export default class WaRadioGroup extends WebAwesomeFormAssociatedElement {
<label <label
part="form-control-label" part="form-control-label"
id="label" id="label"
class="label" class=${classMap({
label: true,
'has-label': hasLabel,
})}
aria-hidden=${hasLabel ? 'false' : 'true'} aria-hidden=${hasLabel ? 'false' : 'true'}
@click=${this.handleLabelClick} @click=${this.handleLabelClick}
> >

View File

@@ -938,7 +938,10 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
<label <label
id="label" id="label"
part="form-control-label label" part="form-control-label label"
class="label" class=${classMap({
label: true,
'has-label': hasLabel,
})}
aria-hidden=${hasLabel ? 'false' : 'true'} aria-hidden=${hasLabel ? 'false' : 'true'}
@click=${this.handleLabelClick} @click=${this.handleLabelClick}
> >

View File

@@ -807,7 +807,7 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement {
id="label" id="label"
part="label" part="label"
for=${this.isRange ? 'thumb-min' : 'text-box'} for=${this.isRange ? 'thumb-min' : 'text-box'}
class=${classMap({ vh: !hasLabel })} class=${classMap({ vh: !hasLabel, 'has-label': hasLabel })}
@pointerdown=${this.handleLabelPointerDown} @pointerdown=${this.handleLabelPointerDown}
> >
<slot name="label">${this.label}</slot> <slot name="label">${this.label}</slot>

View File

@@ -331,7 +331,15 @@ export default class WaTextarea extends WebAwesomeFormAssociatedElement {
const hasHint = this.hint ? true : !!hasHintSlot; const hasHint = this.hint ? true : !!hasHintSlot;
return html` return html`
<label part="form-control-label label" class="label" for="input" aria-hidden=${hasLabel ? 'false' : 'true'}> <label
part="form-control-label label"
class=${classMap({
label: true,
'has-label': hasLabel,
})}
for="input"
aria-hidden=${hasLabel ? 'false' : 'true'}
>
<slot name="label">${this.label}</slot> <slot name="label">${this.label}</slot>
</label> </label>

View File

@@ -7,7 +7,8 @@ export default css`
} }
/* Label */ /* Label */
:is([part~='form-control-label'], [part~='label']):has(*:not(:empty)) { :is([part~='form-control-label'], [part~='label']):has(*:not(:empty)),
:is([part~='form-control-label'], [part~='label']).has-label {
display: inline-flex; display: inline-flex;
color: var(--wa-form-control-label-color); color: var(--wa-form-control-label-color);
font-weight: var(--wa-form-control-label-font-weight); font-weight: var(--wa-form-control-label-font-weight);
@@ -29,7 +30,6 @@ export default css`
line-height: var(--wa-form-control-hint-line-height); line-height: var(--wa-form-control-hint-line-height);
margin-block-start: 0.5em; margin-block-start: 0.5em;
font-size: var(--wa-font-size-smaller); font-size: var(--wa-font-size-smaller);
line-height: var(--wa-form-control-label-line-height);
&:not(.has-slotted) { &:not(.has-slotted) {
display: none; display: none;