diff --git a/coral-component-list/src/scripts/SelectListItem.js b/coral-component-list/src/scripts/SelectListItem.js index c2f968c90d..981744661e 100644 --- a/coral-component-list/src/scripts/SelectListItem.js +++ b/coral-component-list/src/scripts/SelectListItem.js @@ -149,6 +149,19 @@ const SelectListItem = Decorator(class extends BaseComponent(HTMLElement) { return this._elements.icon; } + /** + Sync aria-selected with {@link #selected} when the element has a role that supports it. + Must run after {@link #render} assigns the default {@code role="option"}, because selection + may be set before the role attribute exists (WCAG 4.1.2). + @private + */ + _syncAriaSelected() { + if (this.hasAttribute('role') && + VALID_ARIA_SELECTED_ROLES_REGEXP.test(this.getAttribute('role'))) { + this.setAttribute('aria-selected', this._selected); + } + } + /** Whether the item is selected. @@ -172,10 +185,7 @@ const SelectListItem = Decorator(class extends BaseComponent(HTMLElement) { this._reflectAttribute('selected', this.disabled ? false : this._selected); this.classList.toggle('is-selected', this._selected); - if (this.hasAttribute('role') && - VALID_ARIA_SELECTED_ROLES_REGEXP.test(this.getAttribute('role'))) { - this.setAttribute('aria-selected', this._selected); - } + this._syncAriaSelected(); // Toggle check icon this._elements.checkIcon.hidden = !this._selected; @@ -245,6 +255,8 @@ const SelectListItem = Decorator(class extends BaseComponent(HTMLElement) { // Assign the content zones, moving them into place in the process this.content = content; + + this._syncAriaSelected(); } }); diff --git a/coral-component-list/src/tests/test.SelectList.Item.js b/coral-component-list/src/tests/test.SelectList.Item.js index 8d8107f458..d1b65cc63a 100644 --- a/coral-component-list/src/tests/test.SelectList.Item.js +++ b/coral-component-list/src/tests/test.SelectList.Item.js @@ -47,6 +47,15 @@ describe('SelectList.Item', function () { const el = new SelectList.Item(); expect(el.selected).to.be.false; }); + + it('should expose aria-selected after render when selected was set before role exists (SITES-24721)', function () { + const el = new SelectList.Item(); + el.textContent = 'Default'; + el.selected = true; + helpers.build(el); + expect(el.getAttribute('role')).to.equal('option'); + expect(el.getAttribute('aria-selected')).to.equal('true'); + }); }); describe('#disabled', function () {