diff --git a/packages/field/src/FormControlMixin.js b/packages/field/src/FormControlMixin.js index c835e2922..1fd94e8ca 100644 --- a/packages/field/src/FormControlMixin.js +++ b/packages/field/src/FormControlMixin.js @@ -53,6 +53,34 @@ export const FormControlMixin = dedupeMixin( }; } + get label() { + return ( + (this.querySelector('[slot="label"]') && + this.querySelector('[slot="label"]').textContent) || + this.__label + ); + } + + set label(newValue) { + const oldValue = this.label; + this.__label = newValue; + this.requestUpdate('label', oldValue); + } + + get helpText() { + return ( + (this.querySelector('[slot="help-text"]') && + this.querySelector('[slot="help-text"]').textContent) || + this.__helpText + ); + } + + set helpText(newValue) { + const oldValue = this.helpText; + this.__helpText = newValue; + this.requestUpdate('helpText', oldValue); + } + get slots() { return { ...super.slots, diff --git a/packages/field/src/LionField.js b/packages/field/src/LionField.js index e2ccb2647..8e05f5863 100644 --- a/packages/field/src/LionField.js +++ b/packages/field/src/LionField.js @@ -230,9 +230,6 @@ export class LionField extends FormControlMixin( } get fieldName() { - const label = - this.label || - (this.querySelector('[slot=label]') && this.querySelector('[slot=label]').textContent); - return this.__fieldName || label || this.name; + return this.__fieldName || this.label || this.name; } } diff --git a/packages/field/test/FormControlMixin.test.js b/packages/field/test/FormControlMixin.test.js index df30e8ae9..0325865c7 100644 --- a/packages/field/test/FormControlMixin.test.js +++ b/packages/field/test/FormControlMixin.test.js @@ -23,22 +23,64 @@ describe('FormControlMixin', () => { tag = unsafeStatic(elem); }); - it('has the capability to override the help text', async () => { - const lionFieldAttr = await fixture(html` - <${tag} help-text="This email address is already taken">${inputSlot} + it('has a label', async () => { + const elAttr = await fixture(html` + <${tag} label="Email address">${inputSlot} `); - expect( - Array.from(lionFieldAttr.children).find(child => child.slot === 'help-text').textContent, - ).to.contain('This email address is already taken'); - const lionFieldProp = await fixture(html` + expect(elAttr.label).to.equal('Email address', 'as an attribute'); + + const elProp = await fixture(html` <${tag} - .helpText=${'This email address is already taken'} + .label=${'Email address'} >${inputSlot} `); + expect(elProp.label).to.equal('Email address', 'as a property'); - expect( - Array.from(lionFieldProp.children).find(child => child.slot === 'help-text').textContent, - ).to.contain('This email address is already taken'); + const elElem = await fixture(html` + <${tag}> + + ${inputSlot} + `); + expect(elElem.label).to.equal('Email address', 'as an element'); + }); + + it('has a label that supports inner html', async () => { + const el = await fixture(html` + <${tag}> + + ${inputSlot} + `); + expect(el.label).to.equal('Email address'); + }); + + it('can have a help-text', async () => { + const elAttr = await fixture(html` + <${tag} help-text="We will not send you any spam">${inputSlot} + `); + expect(elAttr.helpText).to.equal('We will not send you any spam', 'as an attribute'); + + const elProp = await fixture(html` + <${tag} + .helpText=${'We will not send you any spam'} + >${inputSlot} + `); + expect(elProp.helpText).to.equal('We will not send you any spam', 'as a property'); + + const elElem = await fixture(html` + <${tag}> + + ${inputSlot} + `); + expect(elElem.helpText).to.equal('We will not send you any spam', 'as an element'); + }); + + it('can have a help-text that supports inner html', async () => { + const el = await fixture(html` + <${tag}> + + ${inputSlot} + `); + expect(el.helpText).to.equal('We will not send you any spam'); }); it('does not duplicate aria-describedby and aria-labelledby ids', async () => { diff --git a/packages/input/stories/index.stories.mdx b/packages/input/stories/index.stories.mdx index b66f2f356..7c3c5b213 100644 --- a/packages/input/stories/index.stories.mdx +++ b/packages/input/stories/index.stories.mdx @@ -10,7 +10,7 @@ import '../lion-input.js'; `lion-input` component is a webcomponent that enhances the functionality of the native `` element. - + {html` `} @@ -25,7 +25,7 @@ import '../lion-input.js'; - Based on [field](?path=/docs/forms-system-overview--page) - Extra visual elements can be added via `slots` - **label**: can also be provided via the `label` attribute, but the slot can be used to change the `html` and `CSS` of the label. - For example add an `sr-only` class to the label to make it visually hidden. + For example add an `u-sr-only` class to the label to make it visually hidden. A label is always needed for accessibility reasons. - **help-text**: a helper text shown below the label to give extra clarification. - **prefix**: does not have an active use case yet, but the option is in place. @@ -49,9 +49,64 @@ import '@lion/input/lion-input.js'; ## Examples +### Label + +Can be provided via the `label` attribute, but the slot can be used to change the `html` and `CSS` of the label. +For example add an `u-sr-only` class to the label to make it (partially) visually hidden. +A label is always needed for accessibility reasons. + + + {html` + + + + + `} + + +```html + + + + +``` + ### Help-text - +A helper text shown below the label to give extra clarification. + +Just like the `label`, a `help-text` can be provided via the `help-text` attribute, a slot can be used to change the `html` and `CSS` of the help-text. +For example add an anchor with further explanation. + + {html`