From 61bf8cb4b1f99a113c95a4b0a6313e95b9a14741 Mon Sep 17 00:00:00 2001 From: gerjanvangeest Date: Thu, 22 Aug 2024 15:08:28 +0200 Subject: [PATCH] fix(select-rich): sets and removes the button role and aria attributes on change of singleOption (#2341) --- .changeset/nice-dots-end.md | 5 ++++ docs/components/select-rich/use-cases.md | 14 +++++----- .../select-rich/src/LionSelectRich.js | 12 +++++++++ .../select-rich/test/lion-select-rich.test.js | 26 +++++++++++++++++++ 4 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 .changeset/nice-dots-end.md diff --git a/.changeset/nice-dots-end.md b/.changeset/nice-dots-end.md new file mode 100644 index 000000000..f307748b4 --- /dev/null +++ b/.changeset/nice-dots-end.md @@ -0,0 +1,5 @@ +--- +'@lion/ui': patch +--- + +[select-rich] sets and removes the button role and aria attributes on change of singleOption diff --git a/docs/components/select-rich/use-cases.md b/docs/components/select-rich/use-cases.md index fa573fe5f..b0fb3cf6d 100644 --- a/docs/components/select-rich/use-cases.md +++ b/docs/components/select-rich/use-cases.md @@ -135,7 +135,7 @@ export const renderOptions = ({ shadowRoot }) => { } return html` - ${objs.map(obj => html` html` ${obj.label} `)}

Full value:


@@ -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.
 
 ```html preview-story
-  
-    Red
-    Hotpink
-    Teal
-  
+
+  Red
+  Hotpink
+  Teal
+
 ```
 
 > By default, the placeholder is completely empty in the `LionSelectInvoker`,
@@ -264,7 +264,7 @@ class SingleOptionRemoveAdd extends LitElement {
       
         
           ${this.options.map(
-            option => html`  `,
+            option => html` ${option} `,
           )}
         
       
diff --git a/packages/ui/components/select-rich/src/LionSelectRich.js b/packages/ui/components/select-rich/src/LionSelectRich.js
index 57c461642..a8dc0df8b 100644
--- a/packages/ui/components/select-rich/src/LionSelectRich.js
+++ b/packages/ui/components/select-rich/src/LionSelectRich.js
@@ -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 (changedProperties.has('_ariaLabelledNodes')) {
         this._invokerNode.setAttribute(
diff --git a/packages/ui/components/select-rich/test/lion-select-rich.test.js b/packages/ui/components/select-rich/test/lion-select-rich.test.js
index 11d9e578a..a0db51cdf 100644
--- a/packages/ui/components/select-rich/test/lion-select-rich.test.js
+++ b/packages/ui/components/select-rich/test/lion-select-rich.test.js
@@ -148,6 +148,32 @@ describe('lion-select-rich', () => {
       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`
+        
+          Item 1
+          Item 2
+        
+      `);
+      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 () => {
       const tagString = defineCE(
         class LionCustomOption extends LionOption {