From bef984d72a534ac4296eaaf30e3cc01eb216e89e Mon Sep 17 00:00:00 2001 From: c0mrade Date: Tue, 26 May 2026 13:50:22 +0300 Subject: [PATCH] fix(scope-selector): drop role=dialog from non-modal popover (a11y) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scope add-popover wrapped its tabs/search/list in role=dialog with no aria-modal and no focus trap. That promises modality to AT but delivers a non-modal popover users can click past — confusing. Remove the wrapper role. The trigger button already exposes the popup via aria-haspopup=listbox + aria-expanded, and the inner div carries role=listbox aria-multiselectable. Nothing for AT to misinterpret now. --- .../ReferralNetwork/components/ScopeSelector.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pages/ReferralNetwork/components/ScopeSelector.tsx b/src/pages/ReferralNetwork/components/ScopeSelector.tsx index e35f9e0..00d453f 100644 --- a/src/pages/ReferralNetwork/components/ScopeSelector.tsx +++ b/src/pages/ReferralNetwork/components/ScopeSelector.tsx @@ -285,13 +285,13 @@ export function ScopeSelector({ value, onAdd, onRemove, onClear, className }: Sc - {/* Dropdown */} + {/* Dropdown — this is a non-modal popover containing tabs + search + + listbox. role="dialog" would imply modality and own the focus, but + we keep the page reachable behind it. The button's aria-haspopup + and aria-expanded already announce the popup; AT can navigate into + it directly. The inner div carries role="listbox". */} {isDropdownOpen && ( -
+
{/* Max reached banner */} {isMaxReached && (