Skip to content

Commit

Permalink
fix(Autocomplete): ensure "no options" is read out in aria-live (#1471)
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker authored Jun 22, 2022
1 parent f469dd8 commit 254303f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 9 deletions.
31 changes: 22 additions & 9 deletions packages/dnb-eufemia/src/components/autocomplete/Autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,11 @@ export default class Autocomplete extends React.PureComponent {
custom_element: PropTypes.object,
custom_method: PropTypes.func,

/**
* For internal use
*/
ariaLiveDelay: PropTypes.number,

on_show: PropTypes.func,
on_type: PropTypes.func,
on_focus: PropTypes.func,
Expand Down Expand Up @@ -315,6 +320,7 @@ export default class Autocomplete extends React.PureComponent {

custom_element: null,
custom_method: null,
ariaLiveDelay: null,

on_show: null,
on_hide: null,
Expand Down Expand Up @@ -1024,14 +1030,16 @@ class AutocompleteInstance extends React.PureComponent {
}
}

hasShowMore = (data = this.context.drawerList.data) => {
hasInjectedDataItem = (data = this.context.drawerList.data) => {
const lastItem = data.slice(-1)[0]
return lastItem && lastItem.show_all === true
return lastItem
? lastItem.show_all || lastItem.__id === 'no_options'
: false
}

countData = (data = this.context.drawerList.data) => {
const count = data.length
return count > 0 && this.hasShowMore(data) ? count - 1 : count
return count > 0 && this.hasInjectedDataItem(data) ? count - 1 : count
}

hasValidData = (data = this.context.drawerList.data) => {
Expand Down Expand Up @@ -1590,12 +1598,16 @@ class AutocompleteInstance extends React.PureComponent {

setAriaLiveUpdate() {
const { opened } = this.context.drawerList
const { aria_live_options, no_options } = this._props
const {
aria_live_options,
no_options,
ariaLiveDelay = 1000,
} = this._props

// this is only to make a better screen reader ux
clearTimeout(this._ariaLiveUpdateTimeout)
this._ariaLiveUpdateTimeout = setTimeout(() => {
if (opened) {
if (opened) {
this._ariaLiveUpdateTimeout = setTimeout(() => {
let newString = null

const count = this.countData()
Expand All @@ -1616,10 +1628,10 @@ class AutocompleteInstance extends React.PureComponent {
ariaLiveUpdate: null,
_listenForPropChanges: false,
})
}, 1e3)
}, 1000)
}
}
}, 1e3) // so that the input gets read out first, and then the results
}, ariaLiveDelay) // so that the input gets read out first, and then the results
}
}

getVocieOverActiveItem(selected_sr) {
Expand Down Expand Up @@ -1722,6 +1734,7 @@ class AutocompleteInstance extends React.PureComponent {
show_all, // eslint-disable-line
aria_live_options, // eslint-disable-line
disable_highlighting, // eslint-disable-line
ariaLiveDelay, // eslint-disable-line

...attributes
} = props
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,66 @@ describe('Autocomplete component', () => {
)
})

it('should update aria-live with results', async () => {
const Comp = mount(
<Component
id="autocomplete-id"
data={mockData}
show_submit_button
ariaLiveDelay={1}
{...mockProps}
/>
)

toggle(Comp)

Comp.find('.dnb-input__input').simulate('change', {
target: { value: 'bb' },
})

await wait(2)

expect(Comp.find('.dnb-sr-only').last().text()).toBe('1 alternativer')
expect(Comp.find('li.dnb-drawer-list__option').at(0).text()).toBe(
mockData[1]
)

Comp.find('.dnb-input__input').simulate('change', {
target: { value: 'cc' },
})

await wait(2)

expect(Comp.find('.dnb-sr-only').last().text()).toBe('2 alternativer')
expect(Comp.find('li.dnb-drawer-list__option').at(0).text()).toBe(
mockData[2].content.join('')
)

Comp.find('.dnb-input__input').simulate('change', {
target: { value: 'c' },
})

await wait(2)

expect(Comp.find('.dnb-sr-only').last().text()).toBe('3 alternativer')
expect(Comp.find('li.dnb-drawer-list__option').at(0).text()).toBe(
mockData[2].content.join('')
)

Comp.find('.dnb-input__input').simulate('change', {
target: { value: 'invalid' },
})

await wait(2)

expect(Comp.find('.dnb-sr-only').last().text()).toBe(
'Ingen alternativer'
)
expect(Comp.find('li.dnb-drawer-list__option').at(0).text()).toBe(
'Ingen alternativer'
)
})

it('will prefer search_content over content', () => {
const mockData = [
{ content: 'item aa', search_content: ['AA c'] },
Expand Down Expand Up @@ -1738,3 +1798,5 @@ const toggle = (Comp) => {
.not('.dnb-input__clear-button')
.simulate('click')
}

const wait = (t) => new Promise((r) => setTimeout(r, t))
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
exports[`Autocomplete markup have to match snapshot 1`] = `
<Autocomplete
align_autocomplete={null}
ariaLiveDelay={1}
aria_live_options="aria_live_options"
class="class"
className="className"
Expand Down Expand Up @@ -96,6 +97,7 @@ exports[`Autocomplete markup have to match snapshot 1`] = `
action_menu={false}
align_autocomplete={null}
align_drawer="left"
ariaLiveDelay={1}
aria_live_options="aria_live_options"
cache_hash={null}
class="class"
Expand Down Expand Up @@ -204,6 +206,7 @@ exports[`Autocomplete markup have to match snapshot 1`] = `
>
<AutocompleteInstance
align_autocomplete={null}
ariaLiveDelay={1}
aria_live_options="aria_live_options"
class="class"
className="className"
Expand Down Expand Up @@ -1121,6 +1124,7 @@ exports[`Autocomplete markup have to match snapshot 1`] = `
context={
Object {
"align_autocomplete": null,
"ariaLiveDelay": 1,
"aria_live_options": "aria_live_options",
"children": "children",
"class": "class",
Expand Down

0 comments on commit 254303f

Please sign in to comment.