Added Aria compliance to the selectablelist.
This commit is contained in:
parent
9ae4b54155
commit
5188570f26
@ -12,16 +12,13 @@ export const SelectableList = <T,>(
|
||||
): JSX.Element => {
|
||||
const { items, selectedValue, renderLabel, onSelect } = props;
|
||||
|
||||
// Track focus state of the list itself
|
||||
const listRef = useRef<HTMLUListElement | null>(null);
|
||||
const isFocusedRef = useRef(false);
|
||||
|
||||
// One ref per item so we can focus + scroll it
|
||||
const itemRefs = useRef<(HTMLLIElement | null)[]>([]);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: React.KeyboardEvent<HTMLUListElement>) => {
|
||||
// Ignore keyboard input unless the list itself is focused
|
||||
if (!isFocusedRef.current) return;
|
||||
if (!items.length) return;
|
||||
|
||||
@ -44,9 +41,8 @@ export const SelectableList = <T,>(
|
||||
[items, selectedValue, onSelect],
|
||||
);
|
||||
|
||||
// Only focus the selected item if the list itself already has focus
|
||||
useEffect(() => {
|
||||
if (!isFocusedRef.current) return; // Do NOT steal focus
|
||||
if (!isFocusedRef.current) return;
|
||||
if (!selectedValue) return;
|
||||
|
||||
const index = items.indexOf(selectedValue);
|
||||
@ -64,6 +60,10 @@ export const SelectableList = <T,>(
|
||||
ref={listRef}
|
||||
className="selectable-list"
|
||||
tabIndex={0}
|
||||
role="listbox"
|
||||
aria-activedescendant={
|
||||
selectedValue ? `option-${items.indexOf(selectedValue)}` : undefined
|
||||
}
|
||||
onFocus={() => (isFocusedRef.current = true)}
|
||||
onBlur={() => (isFocusedRef.current = false)}
|
||||
onKeyDown={handleKeyDown}
|
||||
@ -75,8 +75,11 @@ export const SelectableList = <T,>(
|
||||
return (
|
||||
<li
|
||||
key={index}
|
||||
id={`option-${index}`}
|
||||
ref={(el) => (itemRefs.current[index] = el)}
|
||||
tabIndex={isSelected ? 0 : -1}
|
||||
role="option"
|
||||
aria-selected={isSelected}
|
||||
onClick={() => onSelect(item)}
|
||||
className={className}
|
||||
>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user