From 7e2b9ff0027969035ffe4cd8e6ee76e01a203a8c Mon Sep 17 00:00:00 2001 From: ldanet Date: Sun, 10 Jun 2018 12:11:11 +1200 Subject: [PATCH] Improve accessibility on OSX (#40) --- src/Autowhatever.js | 21 +++++++++++++-------- src/ItemsList.js | 1 + test/helpers.js | 6 +++++- test/plain-list/Autowhatever.test.js | 20 ++++++++++++++++++-- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/Autowhatever.js b/src/Autowhatever.js index 8c05292..dfad48e 100644 --- a/src/Autowhatever.js +++ b/src/Autowhatever.js @@ -304,20 +304,24 @@ export default class Autowhatever extends Component { const renderedItems = multiSection ? this.renderSections() : this.renderItems(); const isOpen = (renderedItems !== null); const ariaActivedescendant = this.getItemId(highlightedSectionIndex, highlightedItemIndex); - const containerProps = theme( - `react-autowhatever-${id}-container`, - 'container', - isOpen && 'containerOpen' - ); const itemsContainerId = `react-autowhatever-${id}`; + const containerProps = { + role: 'combobox', + 'aria-haspopup': 'listbox', + 'aria-owns': itemsContainerId, + 'aria-expanded': isOpen, + ...theme( + `react-autowhatever-${id}-container`, + 'container', + isOpen && 'containerOpen' + ) + }; const inputComponent = renderInputComponent({ type: 'text', value: '', autoComplete: 'off', - role: 'combobox', 'aria-autocomplete': 'list', - 'aria-owns': itemsContainerId, - 'aria-expanded': isOpen, + 'aria-controls': itemsContainerId, 'aria-activedescendant': ariaActivedescendant, ...theme( `react-autowhatever-${id}-input`, @@ -334,6 +338,7 @@ export default class Autowhatever extends Component { const itemsContainer = renderItemsContainer({ containerProps: { id: itemsContainerId, + role: 'listbox', ...theme( `react-autowhatever-${id}-items-container`, 'itemsContainer', diff --git a/src/ItemsList.js b/src/ItemsList.js index a69b8eb..6bf11b6 100644 --- a/src/ItemsList.js +++ b/src/ItemsList.js @@ -50,6 +50,7 @@ export default class ItemsList extends Component { const itemPropsObj = isItemPropsFunction ? itemProps({ sectionIndex, itemIndex }) : itemProps; const allItemProps = { id: getItemId(sectionIndex, itemIndex), + 'aria-selected': isHighlighted, ...theme(itemKey, 'item', isFirst && 'itemFirst', isHighlighted && 'itemHighlighted'), ...itemPropsObj }; diff --git a/test/helpers.js b/test/helpers.js index 1713321..00dc0cc 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -6,10 +6,11 @@ import TestUtils, { Simulate } from 'react-dom/test-utils'; chai.use(sinonChai); -let app, input, itemsContainer; +let app, container, input, itemsContainer; export const init = application => { app = application; + container = TestUtils.findRenderedDOMComponentWithClass(app, 'react-autowhatever__container'); input = TestUtils.findRenderedDOMComponentWithTag(app, 'input'); itemsContainer = TestUtils.findRenderedDOMComponentWithClass(app, 'react-autowhatever__items-container'); }; @@ -29,6 +30,9 @@ export const getStoredInput = () => app.autowhatever.input; export const getStoredItemsContainer = () => app.autowhatever.itemsContainer; export const getStoredHighlightedItem = () => app.autowhatever.highlightedItem; +export const getContainerAttribute = attr => + container.getAttribute(attr); + export const getInputAttribute = attr => input.getAttribute(attr); diff --git a/test/plain-list/Autowhatever.test.js b/test/plain-list/Autowhatever.test.js index 35a81d4..4643498 100644 --- a/test/plain-list/Autowhatever.test.js +++ b/test/plain-list/Autowhatever.test.js @@ -6,9 +6,11 @@ import { getStoredInput, getStoredItemsContainer, getStoredHighlightedItem, + getContainerAttribute, getInputAttribute, getItemsContainerAttribute, getItems, + getItem, mouseEnterItem, mouseLeaveItem, mouseDownItem, @@ -25,8 +27,12 @@ describe('Plain List Autowhatever', () => { }); describe('initially', () => { - it('should set input\'s `aria-owns` to items container\'s `id`', () => { - expect(getInputAttribute('aria-owns')).to.equal(getItemsContainerAttribute('id')); + it('should set container\'s `aria-owns` to items container\'s `id`', () => { + expect(getContainerAttribute('aria-owns')).to.equal(getItemsContainerAttribute('id')); + }); + + it('should set input\'s `aria-controls` to items container\'s `id`', () => { + expect(getInputAttribute('aria-controls')).to.equal(getItemsContainerAttribute('id')); }); it('should render all items', () => { @@ -78,6 +84,16 @@ describe('Plain List Autowhatever', () => { expect(renderItem).to.be.calledWith({ text: 'Apple' }, { isHighlighted: false }); }); + it('should set `aria-selected` to true on highlighted items', () => { + renderItem.reset(); + mouseEnterItem(0); + expect(getItem(0).getAttribute('aria-selected')).to.equal('true'); + + renderItem.reset(); + mouseLeaveItem(0); + expect(getItem(0).getAttribute('aria-selected')).to.equal('false'); + }); + it('should call `renderItem` once when item is left', () => { mouseEnterItem(3); renderItem.reset();