From 119dfc6c3e754e5899abeb65a273ae6222059699 Mon Sep 17 00:00:00 2001 From: Vladyslav Bondarenko Date: Fri, 14 Oct 2022 16:17:29 +0300 Subject: [PATCH] feat: improve screen reader accessibility This allows to follow WAI-ARIA best practices for combobox elements https://www.w3.org/WAI/ARIA/apg/patterns/combobox/ Changes: - Add role="combobox" to the selected country button - Add role="listbox" to the countries list - Refer the countries list by its Id in the combobox element via aria-controls and aria-owns - Add role="option" to each country list option - Use aria-expanded on the combobox element - Refer focused option by its Id in the combobox element via aria-activedescendant to read focused option while navigating by keyboard - Add aria-selected="true" to the selected list option - Set aria-autocomplete="none" to the combobox element since displayed options do not depend on the number input value - Allow passing arbitrary props to the combobox element via flagDropdownProps prop (for example, "aria-labelledby" property can be passed) --- src/components/CountryList.js | 6 ++++++ src/components/FlagBox.js | 8 ++++++++ src/components/FlagDropDown.js | 12 ++++++++++++ src/components/IntlTelInput.js | 5 +++++ 4 files changed, 31 insertions(+) diff --git a/src/components/CountryList.js b/src/components/CountryList.js index a24c7c573..b9723d466 100644 --- a/src/components/CountryList.js +++ b/src/components/CountryList.js @@ -16,6 +16,7 @@ export default class CountryList extends Component { changeHighlightCountry: PropTypes.func, showDropdown: PropTypes.bool, isMobile: PropTypes.bool, + selectedCountryCode: PropTypes.string, } shouldComponentUpdate(nextProps) { @@ -76,6 +77,7 @@ export default class CountryList extends Component { ? () => {} : this.handleMouseOver const keyPrefix = isPreferred ? 'pref-' : '' + const isSelected = this.props.selectedCountryCode === country.iso2 return ( ) }) @@ -122,6 +126,8 @@ export default class CountryList extends Component { this.listElement = listElement }} className={className} + id="intl-tel-countries-list" + role="listbox" > {preferredOptions} {preferredCountries.length > 0 ? divider : null} diff --git a/src/components/FlagBox.js b/src/components/FlagBox.js index 50e3aa647..8f4874230 100644 --- a/src/components/FlagBox.js +++ b/src/components/FlagBox.js @@ -11,6 +11,8 @@ const FlagBox = ({ flagRef, innerFlagRef, countryClass, + isSelected, + index, }) => (
  • @@ -39,6 +45,8 @@ FlagBox.propTypes = { flagRef: PropTypes.func, innerFlagRef: PropTypes.func, countryClass: PropTypes.string.isRequired, + isSelected: PropTypes.bool, + index: PropTypes.number, } FlagBox.defaultProps = { diff --git a/src/components/FlagDropDown.js b/src/components/FlagDropDown.js index c6a1078fa..285ea468b 100644 --- a/src/components/FlagDropDown.js +++ b/src/components/FlagDropDown.js @@ -24,6 +24,7 @@ export default class FlagDropDown extends Component { changeHighlightCountry: PropTypes.func, titleTip: PropTypes.string, refCallback: PropTypes.func.isRequired, + flagDropdownProps: PropTypes.object, // eslint-disable-line react/forbid-prop-types } genSelectedDialCode = () => { @@ -59,6 +60,7 @@ export default class FlagDropDown extends Component { preferredCountries, highlightedCountry, changeHighlightCountry, + countryCode, } = this.props return ( @@ -76,6 +78,7 @@ export default class FlagDropDown extends Component { preferredCountries={preferredCountries} highlightedCountry={highlightedCountry} changeHighlightCountry={changeHighlightCountry} + selectedCountryCode={countryCode} /> ) } @@ -89,16 +92,25 @@ export default class FlagDropDown extends Component { titleTip, dropdownContainer, showDropdown, + highlightedCountry, + flagDropdownProps, } = this.props return (
    {this.genSelectedDialCode()} diff --git a/src/components/IntlTelInput.js b/src/components/IntlTelInput.js index cd0f2d73d..ac81e8085 100644 --- a/src/components/IntlTelInput.js +++ b/src/components/IntlTelInput.js @@ -1302,6 +1302,7 @@ class IntlTelInput extends Component { preferredCountries={this.preferredCountries} highlightedCountry={this.state.highlightedCountry} titleTip={titleTip} + flagDropdownProps={this.props.flagDropdownProps} />