Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

Commit a43f4d7

Browse files
authored
fix(dropdown): cleanup add and remove a11y messages (#1237)
* added cleanup after timeout * addded unit tests * added cleanup * merged the suites together * added changelog * merged the status tests
1 parent c955f39 commit a43f4d7

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
2020
### BREAKING CHANGES
2121
- Rename `inputFocusBorderBottomColor` to `inputFocusBorderColor` in `InputVariables` @layershifter ([#1247](https://github.com/stardust-ui/react/pull/1247))
2222

23+
### Fixes
24+
- Fix a11y message cleanup for add and remove items in `Dropdown` @silviuavram ([#1237](https://github.com/stardust-ui/react/pull/1237))
25+
2326
### Features
2427
- Move `Input` styles to Base theme @layershifter ([#1247](https://github.com/stardust-ui/react/pull/1247))
2528

packages/react/src/components/Dropdown/Dropdown.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ class Dropdown extends AutoControlledComponent<Extendable<DropdownProps>, Dropdo
226226

227227
static className = 'ui-dropdown'
228228

229+
static a11yStatusCleanupTime = 500
230+
229231
static slotClassNames: DropdownSlotClassNames
230232

231233
static propTypes = {
@@ -315,6 +317,12 @@ class Dropdown extends AutoControlledComponent<Extendable<DropdownProps>, Dropdo
315317
}
316318
}
317319

320+
a11yStatusTimeout: any
321+
322+
componentWillUnmount() {
323+
clearTimeout(this.a11yStatusTimeout)
324+
}
325+
318326
public renderComponent({
319327
ElementType,
320328
classes,
@@ -950,6 +958,7 @@ class Dropdown extends AutoControlledComponent<Extendable<DropdownProps>, Dropdo
950958

951959
if (getA11ySelectionMessage && getA11ySelectionMessage.onAdd) {
952960
this.setState({ a11ySelectionStatus: getA11ySelectionMessage.onAdd(item) })
961+
this.setA11ySelectionMessage()
953962
}
954963

955964
if (multiple) {
@@ -1035,6 +1044,7 @@ class Dropdown extends AutoControlledComponent<Extendable<DropdownProps>, Dropdo
10351044

10361045
if (getA11ySelectionMessage && getA11ySelectionMessage.onRemove) {
10371046
this.setState({ a11ySelectionStatus: getA11ySelectionMessage.onRemove(poppedItem) })
1047+
this.setA11ySelectionMessage()
10381048
}
10391049

10401050
this.trySetStateAndInvokeHandler('onSelectedChange', null, { value })
@@ -1130,6 +1140,17 @@ class Dropdown extends AutoControlledComponent<Extendable<DropdownProps>, Dropdo
11301140
// otherwise, highlight no item.
11311141
return null
11321142
}
1143+
1144+
/**
1145+
* Function that sets and cleans the selection message after it has been set,
1146+
* so it is not read anymore via virtual cursor.
1147+
*/
1148+
private setA11ySelectionMessage = (): void => {
1149+
clearTimeout(this.a11yStatusTimeout)
1150+
this.a11yStatusTimeout = setTimeout(() => {
1151+
this.setState({ a11ySelectionStatus: '' })
1152+
}, Dropdown.a11yStatusCleanupTime)
1153+
}
11331154
}
11341155

11351156
Dropdown.slotClassNames = {

packages/react/test/specs/components/Dropdown/Dropdown-test.tsx

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import * as _ from 'lodash'
44

55
import Dropdown from 'src/components/Dropdown/Dropdown'
66
import DropdownSearchInput from 'src/components/Dropdown/DropdownSearchInput'
7+
import DropdownSelectedItem from 'src/components/Dropdown/DropdownSelectedItem'
78
import { isConformant } from 'test/specs/commonTests'
89
import { mountWithProvider } from 'test/utils'
910

1011
jest.dontMock('keyboard-key')
12+
jest.useFakeTimers()
1113

1214
describe('Dropdown', () => {
1315
const items = ['item1', 'item2', 'item3', 'item4', 'item5']
@@ -780,6 +782,10 @@ describe('Dropdown', () => {
780782
})
781783

782784
describe('getA11ySelectionMessage', () => {
785+
afterEach(() => {
786+
jest.runAllTimers()
787+
})
788+
783789
it('creates message container element', () => {
784790
mountWithProvider(<Dropdown options={[]} getA11ySelectionMessage={{}} />)
785791
expect(
@@ -788,6 +794,53 @@ describe('Dropdown', () => {
788794
),
789795
).toBeTruthy()
790796
})
797+
798+
it('has the onAdd message inserted and cleared after an item has been added to selection', () => {
799+
const wrapper = mountWithProvider(
800+
<Dropdown
801+
multiple
802+
items={items}
803+
getA11ySelectionMessage={{ onAdd: item => 'bla bla added' }}
804+
/>,
805+
)
806+
const dropdown = wrapper.find(Dropdown)
807+
const triggerButton = wrapper.find(`button.${Dropdown.slotClassNames.triggerButton}`)
808+
809+
triggerButton.simulate('click')
810+
const firstItem = wrapper.find(`li.${Dropdown.slotClassNames.item}`).at(0)
811+
firstItem.simulate('click')
812+
813+
expect(dropdown.state('a11ySelectionStatus')).toBe('bla bla added')
814+
815+
jest.runAllTimers()
816+
817+
expect(dropdown.state('a11ySelectionStatus')).toBe('')
818+
})
819+
820+
it('has the onRemove message inserted and cleared after an item has been removed from selection', () => {
821+
const wrapper = mountWithProvider(
822+
<Dropdown
823+
multiple
824+
items={items}
825+
getA11ySelectionMessage={{ onRemove: item => 'bla bla removed' }}
826+
/>,
827+
)
828+
const dropdown = wrapper.find(Dropdown)
829+
const triggerButton = wrapper.find(`button.${Dropdown.slotClassNames.triggerButton}`)
830+
831+
triggerButton.simulate('click')
832+
const firstItem = wrapper.find(`li.${Dropdown.slotClassNames.item}`).at(0)
833+
firstItem.simulate('click')
834+
jest.runAllTimers()
835+
const removeIcon = wrapper.find(`span.${DropdownSelectedItem.slotClassNames.icon}`)
836+
removeIcon.simulate('click')
837+
838+
expect(dropdown.state('a11ySelectionStatus')).toBe('bla bla removed')
839+
840+
jest.runAllTimers()
841+
842+
expect(dropdown.state('a11ySelectionStatus')).toBe('')
843+
})
791844
})
792845

793846
describe('searchQuery', () => {

0 commit comments

Comments
 (0)