From 048041194d6082cfc8cecfc0eeb63dce65b10e42 Mon Sep 17 00:00:00 2001 From: Henrique Limas Date: Fri, 20 Dec 2024 15:42:16 -0300 Subject: [PATCH] fix(EbayListboxButton): Show listbox with active descendent on button focus (#382) --- .../__tests__/index.spec.tsx | 28 ++++++++++++++++++- .../listbox-button-option.tsx | 2 -- src/ebay-listbox-button/listbox-button.tsx | 12 +++----- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/ebay-listbox-button/__tests__/index.spec.tsx b/src/ebay-listbox-button/__tests__/index.spec.tsx index 8e9bce8a..2990fa69 100644 --- a/src/ebay-listbox-button/__tests__/index.spec.tsx +++ b/src/ebay-listbox-button/__tests__/index.spec.tsx @@ -1,5 +1,7 @@ +/// import React from 'react' -import { fireEvent, render, screen } from '@testing-library/react' +import { act, fireEvent, render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' import { eventOfType } from '../../common/event-utils/__tests__/helpers' import { EbayListboxButton, EbayListboxButtonOption } from '..' @@ -37,6 +39,30 @@ describe('', () => { expect(buttonElement).not.toHaveAttribute('aria-labelledby') }) + + it('should render aria-activedescendant with selected option id', async () => { + await renderListbox() + + act(() => { + userEvent.click(screen.getByRole('button')) + }) + + act(() => { + userEvent.click(screen.getAllByRole('option')[1]) + }) + + expect(screen.getByRole('listbox')).toHaveAttribute('aria-activedescendant', screen.getAllByRole('option')[1].id) + }) + + it('should render aria-activedescendant on focus of the button', async () => { + await renderListbox() + + expect(screen.queryByRole('listbox')).not.toBeInTheDocument() + + fireEvent.focus(screen.getByRole('button')) + + expect(screen.getByRole('listbox')).toHaveAttribute('aria-activedescendant', screen.getAllByRole('option')[1].id) + }) }) describe('on render', () => { diff --git a/src/ebay-listbox-button/listbox-button-option.tsx b/src/ebay-listbox-button/listbox-button-option.tsx index 814c2244..0181515d 100644 --- a/src/ebay-listbox-button/listbox-button-option.tsx +++ b/src/ebay-listbox-button/listbox-button-option.tsx @@ -17,7 +17,6 @@ const ListboxOption: FC = ({ index, innerRef, className, - id, ...rest }) => { const wrapperClassName = classNames(`listbox-button__option`, className, @@ -27,7 +26,6 @@ const ListboxOption: FC = ({ {...rest} className={wrapperClassName} role="option" - id={id || `listbox_btn_${value}_${index}`} aria-selected={selected} ref={innerRef} onClick={(e) => {onClick(e, value, index)}} diff --git a/src/ebay-listbox-button/listbox-button.tsx b/src/ebay-listbox-button/listbox-button.tsx index 188fbc6f..b2de6ba9 100644 --- a/src/ebay-listbox-button/listbox-button.tsx +++ b/src/ebay-listbox-button/listbox-button.tsx @@ -14,7 +14,7 @@ export type ChangeEventProps = { wasClicked: boolean; } -export type EbayListboxButtonProps = Omit, 'onChange'> & { +export type EbayListboxButtonProps = Omit, 'onChange'> & { selected?: number; borderless?: boolean; fluid?: boolean; @@ -89,10 +89,6 @@ const ListboxButton: FC = ({ const getIndexByValue = useCallback((selectedValue) => childrenArray.findIndex(({ props }) => props.value === selectedValue), [childrenArray]) const getSelectedOption = (currentIndex: number) => optionsByIndexRef.current.get(currentIndex) - const setActiveDescendant = (index: number) => { - const optionsContainerEle = optionsContainerRef.current - optionsContainerEle?.setAttribute(`aria-activedescendant`, getSelectedOption(index).id) - } const collapseListbox = () => { setExpanded(false) @@ -117,7 +113,6 @@ const ListboxButton: FC = ({ setSelectedOption(childrenArray[index]) setSelectedIndex(index) collapseListbox() - setActiveDescendant(index) buttonRef.current.focus() onChange(e, { index, selected: [getSelectedValueByIndex(index)], wasClicked }) setWasClicked(false) @@ -160,7 +155,6 @@ const ListboxButton: FC = ({ makeOptionActive(selectedIndex === undefined || updatedIndex === -1 ? 0 : updatedIndex) makeOptionInActive(selectedIndex === undefined || selectedIndex === -1 ? 0 : selectedIndex) scrollOptions(updatedIndex) - setActiveDescendant(updatedIndex) setSelectedIndex(updatedIndex) setSelectedOption(childrenArray[updatedIndex]) } @@ -169,7 +163,6 @@ const ListboxButton: FC = ({ setTimeout(() => optionsContainerRef?.current?.focus(focusOptions), 0) const onButtonClick = () => { toggleListbox() - setOptionsOpened(true) focusOptionsContainer({ preventScroll: true }) } const onButtonKeyup = (e: KeyboardEvent) => { @@ -233,6 +226,7 @@ const ListboxButton: FC = ({ index, key: index, selected: selectedOption && child.props.value === selectedOption.props.value, + id: child.props.id || `listbox_btn_${child.props.value}_${index}`, onClick: (e) => onOptionsSelect(e, index), innerRef: optionNode => !optionNode ? optionsByIndexRef.current.delete(index) @@ -261,6 +255,7 @@ const ListboxButton: FC = ({