fix(select-rich): sets and removes the button role and aria attributes on change of singleOption (#2341)

This commit is contained in:
gerjanvangeest 2024-08-22 15:08:28 +02:00 committed by GitHub
parent e0ef676a36
commit 61bf8cb4b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 50 additions and 7 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': patch
---
[select-rich] sets and removes the button role and aria attributes on change of singleOption

View file

@ -135,7 +135,7 @@ export const renderOptions = ({ shadowRoot }) => {
} }
return html` return html`
<lion-select-rich label="Credit Card" name="color" @model-value-changed="${showOutput}"> <lion-select-rich label="Credit Card" name="color" @model-value-changed="${showOutput}">
${objs.map(obj => html` <lion-option .choiceValue="${obj}>${obj.label}</lion-option> `)}" ${objs.map(obj => html` <lion-option .choiceValue="${obj}">${obj.label}</lion-option> `)}
</lion-select-rich> </lion-select-rich>
<p>Full value:</p> <p>Full value:</p>
<pre id="demoRenderOutput"></pre> <pre id="demoRenderOutput"></pre>
@ -222,11 +222,11 @@ Often, you may want a placeholder that appears initially, but cannot be selected
For this you can use `has-no-default-selected` attribute. For this you can use `has-no-default-selected` attribute.
```html preview-story ```html preview-story
<lion-select-rich name="favoriteColor" label="Favorite color" has-no-default-selected> <lion-select-rich name="favoriteColor" label="Favorite color" has-no-default-selected>
<lion-option .choiceValue="${'red'}">Red</lion-option> <lion-option .choiceValue="${'red'}">Red</lion-option>
<lion-option .choiceValue="${'hotpink'}">Hotpink</lion-option> <lion-option .choiceValue="${'hotpink'}">Hotpink</lion-option>
<lion-option .choiceValue="${'teal'}">Teal</lion-option> <lion-option .choiceValue="${'teal'}">Teal</lion-option>
</lion-select-rich> </lion-select-rich>
``` ```
> By default, the placeholder is completely empty in the `LionSelectInvoker`, > By default, the placeholder is completely empty in the `LionSelectInvoker`,
@ -264,7 +264,7 @@ class SingleOptionRemoveAdd extends LitElement {
<lion-select-rich name="favoriteColor" label="Favorite color"> <lion-select-rich name="favoriteColor" label="Favorite color">
<lion-options slot="input"> <lion-options slot="input">
${this.options.map( ${this.options.map(
option => html` <lion-option .choiceValue="${option}>${option}"</lion-option> `, option => html` <lion-option .choiceValue="${option}">${option}</lion-option> `,
)} )}
</lion-options> </lion-options>
</lion-select-rich> </lion-select-rich>

View file

@ -196,6 +196,18 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L
} }
} }
if (changedProperties.has('singleOption')) {
if (this.singleOption) {
this._invokerNode.removeAttribute('role');
this._invokerNode.removeAttribute('aria-haspopup');
this._invokerNode.removeAttribute('aria-expanded');
} else {
this._invokerNode.setAttribute('role', 'button');
this._invokerNode.setAttribute('aria-haspopup', 'listbox');
this._invokerNode.setAttribute('aria-expanded', `${this.opened}`);
}
}
if (this._inputNode && this._invokerNode) { if (this._inputNode && this._invokerNode) {
if (changedProperties.has('_ariaLabelledNodes')) { if (changedProperties.has('_ariaLabelledNodes')) {
this._invokerNode.setAttribute( this._invokerNode.setAttribute(

View file

@ -148,6 +148,32 @@ describe('lion-select-rich', () => {
expect(_invokerNode.hasAttribute('single-option')).to.be.true; expect(_invokerNode.hasAttribute('single-option')).to.be.true;
}); });
it('sets and removes the button role and aria attributes on change of singleOption', async () => {
const el = await fixture(html`
<lion-select-rich>
<lion-option .choiceValue=${10}>Item 1</lion-option>
<lion-option .choiceValue=${20}>Item 2</lion-option>
</lion-select-rich>
`);
const { _invokerNode } = getSelectRichMembers(el);
expect(_invokerNode.hasAttribute('role')).to.be.true;
expect(_invokerNode.hasAttribute('aria-haspopup')).to.be.true;
expect(_invokerNode.hasAttribute('aria-expanded')).to.be.true;
el.singleOption = true;
await el.updateComplete;
expect(_invokerNode.hasAttribute('role')).to.be.false;
expect(_invokerNode.hasAttribute('aria-haspopup')).to.be.false;
expect(_invokerNode.hasAttribute('aria-expanded')).to.be.false;
el.singleOption = false;
await el.updateComplete;
expect(_invokerNode.hasAttribute('role')).to.be.true;
expect(_invokerNode.hasAttribute('aria-haspopup')).to.be.true;
expect(_invokerNode.hasAttribute('aria-expanded')).to.be.true;
});
it('updates the invoker when the selected element is the same but the modelValue was updated asynchronously', async () => { it('updates the invoker when the selected element is the same but the modelValue was updated asynchronously', async () => {
const tagString = defineCE( const tagString = defineCE(
class LionCustomOption extends LionOption { class LionCustomOption extends LionOption {