From a8953c196b18aa3bc34f66cf853104863704204f Mon Sep 17 00:00:00 2001 From: Denis Kashkovsky Date: Wed, 16 Jan 2019 17:11:47 +0200 Subject: [PATCH] Issue #3352: Aria messages cannot be localized and one of the messages contains wrong statement --- src/Select.js | 48 ++++++++++---- .../__snapshots__/Async.test.js.snap | 65 +++++++++++++++++++ .../__snapshots__/AsyncCreatable.test.js.snap | 65 +++++++++++++++++++ .../__snapshots__/Select.test.js.snap | 56 ++++++++++++++++ .../__snapshots__/StateManaged.test.js.snap | 9 +++ src/accessibility/index.js | 2 +- 6 files changed, 232 insertions(+), 13 deletions(-) diff --git a/src/Select.js b/src/Select.js index efaa5f4b54..0b37a5d43b 100644 --- a/src/Select.js +++ b/src/Select.js @@ -75,6 +75,21 @@ type FormatOptionLabelMeta = { inputValue: string, selectValue: ValueType, }; +export type Accessibility = { + valueFocusAriaMessage: (args: { + focusedValue?: OptionType, + getOptionLabel: (data: OptionType) => string, + selectValue: OptionsType | Array + }) => string, + optionFocusAriaMessage: (args: { + focusedOption: OptionType, + getOptionLabel: (data: OptionType) => string, + options: OptionsType + }) => string, + resultsAriaMessage: (args: { inputValue: string, screenReaderMessage: string }) => string, + valueEventAriaMessage: (event: any, context: ValueEventContext) => string, + instructionsAriaMessage: (event: any, context?: InstructionsContext) => string +}; export type Props = { /* Aria label (for assistive tech) */ @@ -244,7 +259,9 @@ export type Props = { /* The value of the select; reflected by the selected option */ value: ValueType, /* A CSP Nonce which will be used in injected style sheets */ - nonce?: string + nonce?: string, + /* Custom ARIA message functions */ + accessibility?: Accessibility }; export const defaultProps = { @@ -285,6 +302,13 @@ export const defaultProps = { styles: {}, tabIndex: '0', tabSelectsValue: true, + accessibility: { + valueFocusAriaMessage, + optionFocusAriaMessage, + resultsAriaMessage, + valueEventAriaMessage, + instructionsAriaMessage + }, }; type MenuOptions = { @@ -798,7 +822,7 @@ export default class Select extends Component { context: ValueEventContext, }) => { this.setState({ - ariaLiveSelection: valueEventAriaMessage(event, context), + ariaLiveSelection: this.props.accessibility ? this.props.accessibility.valueEventAriaMessage(event, context) : '', }); }; announceAriaLiveContext = ({ @@ -809,10 +833,10 @@ export default class Select extends Component { context?: InstructionsContext, }) => { this.setState({ - ariaLiveContext: instructionsAriaMessage(event, { + ariaLiveContext: this.props.accessibility ? this.props.accessibility.instructionsAriaMessage(event, { ...context, label: this.props['aria-label'], - }), + }) : '', }); }; @@ -1337,11 +1361,11 @@ export default class Select extends Component { focusedValue, focusedOption, } = this.state; - const { options, menuIsOpen, inputValue, screenReaderStatus } = this.props; + const { options, menuIsOpen, inputValue, screenReaderStatus, accessibility } = this.props; // An aria live message representing the currently focused value in the select. - const focusedValueMsg = focusedValue - ? valueFocusAriaMessage({ + const focusedValueMsg = focusedValue && accessibility + ? accessibility.valueFocusAriaMessage({ focusedValue, getOptionLabel: this.getOptionLabel, selectValue, @@ -1349,18 +1373,18 @@ export default class Select extends Component { : ''; // An aria live message representing the currently focused option in the select. const focusedOptionMsg = - focusedOption && menuIsOpen - ? optionFocusAriaMessage({ + focusedOption && menuIsOpen && accessibility + ? accessibility.optionFocusAriaMessage({ focusedOption, getOptionLabel: this.getOptionLabel, options, }) : ''; // An aria live message representing the set of focusable results and current searchterm/inputvalue. - const resultsMsg = resultsAriaMessage({ + const resultsMsg = accessibility ? accessibility.resultsAriaMessage({ inputValue, screenReaderMessage: screenReaderStatus({ count: this.countOptions() }), - }); + }) : ''; return `${focusedValueMsg} ${focusedOptionMsg} ${resultsMsg} ${ariaLiveContext}`; } @@ -1390,7 +1414,7 @@ export default class Select extends Component { readOnly disabled={isDisabled} tabIndex={tabIndex} - value="" + value='' emotion={this.emotion} /> ); diff --git a/src/__tests__/__snapshots__/Async.test.js.snap b/src/__tests__/__snapshots__/Async.test.js.snap index 8006c4ead6..47d785609b 100644 --- a/src/__tests__/__snapshots__/Async.test.js.snap +++ b/src/__tests__/__snapshots__/Async.test.js.snap @@ -17,6 +17,15 @@ exports[`defaults - snapshot 1`] = ` options={Array []} > snapshot 1`] = `