Skip to content

Commit

Permalink
fix(Autocomplete): enhance VoiceOver support (#1472)
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker authored Jun 22, 2022
1 parent 6607963 commit f469dd8
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 65 deletions.

Large diffs are not rendered by default.

42 changes: 32 additions & 10 deletions packages/dnb-eufemia/src/components/autocomplete/Autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ import FormStatus from '../form-status/FormStatus'
import IconPrimary from '../icon-primary/IconPrimary'
import Input, { SubmitButton } from '../input/Input'
import ProgressIndicator from '../progress-indicator/ProgressIndicator'
import DrawerList from '../../fragments/drawer-list/DrawerList'
import DrawerList, {
ItemContent,
} from '../../fragments/drawer-list/DrawerList'
import DrawerListContext from '../../fragments/drawer-list/DrawerListContext'
import DrawerListProvider from '../../fragments/drawer-list/DrawerListProvider'
import {
Expand Down Expand Up @@ -72,6 +74,7 @@ export default class Autocomplete extends React.PureComponent {
PropTypes.node,
]),
show_options_sr: PropTypes.string,
selected_sr: PropTypes.string,
submit_button_title: PropTypes.string,
submit_button_icon: PropTypes.oneOfType([
PropTypes.string,
Expand Down Expand Up @@ -249,6 +252,7 @@ export default class Autocomplete extends React.PureComponent {
aria_live_options: null,
indicator_label: null,
show_options_sr: null,
selected_sr: null,
submit_button_title: null,
submit_button_icon: 'chevron_down',
input_ref: null,
Expand Down Expand Up @@ -1618,6 +1622,30 @@ class AutocompleteInstance extends React.PureComponent {
}, 1e3) // so that the input gets read out first, and then the results
}

getVocieOverActiveItem(selected_sr) {
// Add VoiceOver support to read the "selected" item
if (IS_MAC) {
const { active_item, selected_item } = this.context.drawerList
const currentDataItem = getCurrentData(
active_item,
this.context.drawerList.data
)

return (
<span className="dnb-sr-only" aria-live="assertive" aria-atomic>
{currentDataItem && (
<>
<ItemContent>{currentDataItem}</ItemContent>
{active_item === selected_item ? <> {selected_sr}</> : null}
</>
)}
</span>
)
}

return null
}

render() {
// use only the props from context, who are available here anyway
const props = (this._props = extendPropsWithContext(
Expand Down Expand Up @@ -1665,6 +1693,7 @@ class AutocompleteInstance extends React.PureComponent {
search_numbers, // eslint-disable-line
search_in_word_index, // eslint-disable-line
show_options_sr, // eslint-disable-line
selected_sr,
submit_button_title,
submit_button_icon,
portal_class,
Expand Down Expand Up @@ -1963,15 +1992,8 @@ class AutocompleteInstance extends React.PureComponent {
</span>
</span>

{/* Help VO to read the list, as long as no input changes are made we need that (&& _input_value === inputValue) */}
{IS_MAC && (
<span className="dnb-sr-only" aria-live="assertive">
{AutocompleteInstance.getCurrentDataTitle(
active_item,
this.context.drawerList.original_data
)}
</span>
)}
{/* Add VoiceOver support to read the "selected" item */}
{this.getVocieOverActiveItem(selected_sr)}

<span className="dnb-sr-only" aria-live="assertive">
{ariaLiveUpdate}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
loadScss,
attachToBody,
} from '../../../core/jest/jestSetup'
import * as helpers from '../../../shared/helpers'
import Component from '../Autocomplete'
import { SubmitButton } from '../../../components/input/Input'
import { format } from '../../../components/number-format/NumberUtils'
Expand Down Expand Up @@ -271,6 +272,56 @@ describe('Autocomplete component', () => {
)
})

it('should update aria-live (for VoiceOver support) with selected item', () => {
// eslint-disable-next-line
helpers.IS_MAC = true

const Comp = mount(
<Component
id="autocomplete-id"
data={mockData}
show_submit_button
{...mockProps}
/>
)

toggle(Comp)

expect(Comp.find('.dnb-sr-only').first().text()).toBe('')

// simulate changes
keydown(Comp, 40) // down

expect(Comp.find('.dnb-sr-only').first().text()).toBe('AA c')

// simulate changes
keydown(Comp, 40) // down

expect(Comp.find('.dnb-sr-only').first().text()).toBe('BB cc zethx')

// simulate changes
keydown(Comp, 40) // down

expect(Comp.find('.dnb-sr-only').first().text()).toBe('CCcc')

keydown(Comp, 13) // enter

expect(Comp.find('.dnb-sr-only').first().text()).toBe('CCcc Valgt')

// simulate changes
keydown(Comp, 38) // up

expect(Comp.find('.dnb-sr-only').first().text()).toBe('BB cc zethx')

// eslint-disable-next-line
helpers.IS_MAC = false

// simulate changes
keydown(Comp, 38) // up

expect(Comp.find('.dnb-sr-only').first().text()).toBe('')
})

it('can be used with regex chars', () => {
const mockData = [
'AA aa',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ exports[`Autocomplete markup have to match snapshot 1`] = `
scrollable="scrollable"
search_in_word_index="search_in_word_index"
search_numbers="search_numbers"
selected_sr="selected_sr"
show_all="show_all"
show_clear_button="show_clear_button"
show_options_sr="show_options_sr"
Expand Down Expand Up @@ -176,6 +177,7 @@ exports[`Autocomplete markup have to match snapshot 1`] = `
scrollable="scrollable"
search_in_word_index="search_in_word_index"
search_numbers="search_numbers"
selected_sr="selected_sr"
show_all="show_all"
show_clear_button="show_clear_button"
show_options_sr="show_options_sr"
Expand Down Expand Up @@ -270,6 +272,7 @@ exports[`Autocomplete markup have to match snapshot 1`] = `
scrollable="scrollable"
search_in_word_index="search_in_word_index"
search_numbers="search_numbers"
selected_sr="selected_sr"
show_all="show_all"
show_clear_button="show_clear_button"
show_options_sr="show_options_sr"
Expand Down Expand Up @@ -1185,6 +1188,7 @@ exports[`Autocomplete markup have to match snapshot 1`] = `
"scrollable": "scrollable",
"search_in_word_index": "search_in_word_index",
"search_numbers": "search_numbers",
"selected_sr": "selected_sr",
"show_all": "show_all",
"show_clear_button": "show_clear_button",
"show_options_sr": "show_options_sr",
Expand Down
10 changes: 3 additions & 7 deletions packages/dnb-eufemia/src/fragments/drawer-list/DrawerList.js
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ DrawerList.Item.defaultProps = {
value: null,
}

const ItemContent = ({ hash, children }) => {
export function ItemContent({ hash = '', children }) {
if (Array.isArray(children.content || children)) {
return (children.content || children).map((item, n) => (
<span key={hash + n} className="dnb-drawer-list__option__item">
Expand All @@ -573,12 +573,8 @@ const ItemContent = ({ hash, children }) => {
return children
}
ItemContent.propTypes = {
hash: PropTypes.string.isRequired,
children: PropTypes.oneOfType([
PropTypes.node,
PropTypes.func,
PropTypes.object,
]).isRequired,
hash: PropTypes.string,
children: PropTypes.oneOfType([PropTypes.node, PropTypes.object]),
}

DrawerList.HorizontalItem = ({ className, ...props }) => (
Expand Down
1 change: 1 addition & 0 deletions packages/dnb-eufemia/src/shared/locales/en-GB.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export default {
show_all: 'Show everything',
show_options_sr: 'Browse options, close with esc button',
aria_live_options: '%s options',
selected_sr: 'Selected',
indicator_label: 'Getting data ...',
},
Modal: {
Expand Down
1 change: 1 addition & 0 deletions packages/dnb-eufemia/src/shared/locales/nb-NO.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export default {
show_all: 'Vis alt',
show_options_sr: 'Bla gjennom alternativer, lukk med esc knappen',
aria_live_options: '%s alternativer',
selected_sr: 'Valgt',
indicator_label: 'Henter data ...',
},
Modal: {
Expand Down

0 comments on commit f469dd8

Please sign in to comment.