From d7bafaf3704ac0f203a4837b85705e46813e7483 Mon Sep 17 00:00:00 2001 From: Amir Baghdoust Date: Mon, 27 Apr 2026 19:20:00 +0200 Subject: [PATCH] fix(dropdown-select): propagate aria-details-id to combobox element (#2443) The aria-details-id prop now correctly sets aria-details on the inner combobox trigger, aligning dropdown-select with other field components. When helper text exists, aria-describedby includes both IDs. Guard added so aria-describedby is not rendered when empty. Closes #2443 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../dropdown-select/dropdown-select.spec.ts | 49 +++++++++++++++++++ .../dropdown-select/dropdown-select.tsx | 11 +++-- .../components/src/html/dropdown-select.html | 4 ++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/packages/components/src/components/dropdown-select/dropdown-select.spec.ts b/packages/components/src/components/dropdown-select/dropdown-select.spec.ts index 201b20318e..8b8615a006 100644 --- a/packages/components/src/components/dropdown-select/dropdown-select.spec.ts +++ b/packages/components/src/components/dropdown-select/dropdown-select.spec.ts @@ -49,6 +49,55 @@ describe('DropdownSelect', function () { expect(comboboxEl.textContent).toBe('Cedric'); }); + it('should propagate aria details id to the combobox when no helper text is set', async () => { + const ariaDetailsId = 'dropdown-select-extra-details'; + const page = await newSpecPage({ + components: [DropdownSelect], + html: ` + + Caspar + Cedric + `, + }); + + const selectEl = page.doc.querySelector('scale-dropdown-select'); + const comboboxEl = selectEl.shadowRoot.querySelector( + '[part="combobox"]' + ) as HTMLElement; + + expect(comboboxEl.getAttribute('aria-describedby')).toBe(ariaDetailsId); + expect(comboboxEl.getAttribute('aria-details')).toBe(ariaDetailsId); + }); + + it('should keep helper text as aria-describedby and aria details on the combobox', async () => { + const ariaDetailsId = 'dropdown-select-extra-details'; + const page = await newSpecPage({ + components: [DropdownSelect], + html: ` + + Caspar + Cedric + `, + }); + + const selectEl = page.doc.querySelector('scale-dropdown-select'); + const comboboxEl = selectEl.shadowRoot.querySelector( + '[part="combobox"]' + ) as HTMLElement; + const helperTextEl = selectEl.shadowRoot.querySelector( + 'scale-helper-text' + ) as HTMLElement; + + expect(comboboxEl.getAttribute('aria-describedby')).toBe( + `${helperTextEl.id} ${ariaDetailsId}` + ); + expect(comboboxEl.getAttribute('aria-details')).toBe(ariaDetailsId); + }); + it('should be able to change it`s value via click and emit an event', async () => { const page = await newSpecPage({ components: [DropdownSelect], diff --git a/packages/components/src/components/dropdown-select/dropdown-select.tsx b/packages/components/src/components/dropdown-select/dropdown-select.tsx index 463b79c411..4db8d9d22c 100644 --- a/packages/components/src/components/dropdown-select/dropdown-select.tsx +++ b/packages/components/src/components/dropdown-select/dropdown-select.tsx @@ -495,8 +495,13 @@ export class DropdownSelect { const ValueElement = element.ItemElement; const hasEmptyValueElement = element.value === ''; const helperTextId = `helper-message-${generateUniqueId()}`; - const describedBy = this.helperText ? helperTextId : this.ariaDetailsId; - const ariaDescribedByAttr = { 'aria-describedBy': describedBy }; + const describedBy = [ + this.helperText ? helperTextId : null, + this.ariaDetailsId, + ] + .filter(Boolean) + .join(' '); + const ariaDescribedByAttr = { 'aria-describedby': describedBy }; return ( @@ -528,7 +533,7 @@ export class DropdownSelect { ).value, } : {})} - {...ariaDescribedByAttr} + {...(describedBy ? ariaDescribedByAttr : {})} {...(this.invalid ? { 'aria-invalid': 'true' } : {})} > diff --git a/packages/components/src/html/dropdown-select.html b/packages/components/src/html/dropdown-select.html index 901f6fd688..1817eb6d0e 100644 --- a/packages/components/src/html/dropdown-select.html +++ b/packages/components/src/html/dropdown-select.html @@ -28,6 +28,7 @@ label="Favorite person" id="person-select" helper-text="not Jerry!" + aria-details-id="person-select-extra-details" size="small" invalid value="caspar" @@ -125,6 +126,9 @@ >Davin +
+ Choose a person who can take over the request if needed. +
choose Dario