From af8a22229c5c824b83047056b6d3c533e7e9ab38 Mon Sep 17 00:00:00 2001 From: Mohammer5 Date: Mon, 21 Oct 2024 18:39:31 +0800 Subject: [PATCH] feat(select a11y): handle pageUp and pageDown keys --- .../src/single-select-a11y/menu/index.js | 1 + .../{ => menu}/menu-filter.js | 2 +- .../{ => menu}/menu-loading.js | 0 .../{ => menu}/menu-options-list.js | 51 ++++----- .../src/single-select-a11y/{ => menu}/menu.js | 12 +- .../single-select-a11y/{ => menu}/option.js | 1 + .../selected-value/index.js | 1 + .../selected-value-clear-button.js | 2 +- .../selected-value-container.js | 0 .../selected-value-placeholder.js | 0 .../selected-value-prefix.js | 0 .../{ => selected-value}/selected-value.js | 0 .../single-select-a11y/shared-prop-types.js | 14 +-- .../single-select-a11y/single-select-a11y.js | 16 +-- .../single-select-a11y.prod.stories.js | 39 +++++-- .../use-handle-key-press/index.js | 1 + .../use-handle-key-press.js | 90 +++------------ .../use-handle-key-press/use-handle-typing.js | 74 +++++++++++++ .../use-handle-key-press/use-page-up-down.js | 103 ++++++++++++++++++ 19 files changed, 275 insertions(+), 132 deletions(-) create mode 100644 components/select/src/single-select-a11y/menu/index.js rename components/select/src/single-select-a11y/{ => menu}/menu-filter.js (97%) rename components/select/src/single-select-a11y/{ => menu}/menu-loading.js (100%) rename components/select/src/single-select-a11y/{ => menu}/menu-options-list.js (78%) rename components/select/src/single-select-a11y/{ => menu}/menu.js (91%) rename components/select/src/single-select-a11y/{ => menu}/option.js (98%) create mode 100644 components/select/src/single-select-a11y/selected-value/index.js rename components/select/src/single-select-a11y/{ => selected-value}/selected-value-clear-button.js (98%) rename components/select/src/single-select-a11y/{ => selected-value}/selected-value-container.js (100%) rename components/select/src/single-select-a11y/{ => selected-value}/selected-value-placeholder.js (100%) rename components/select/src/single-select-a11y/{ => selected-value}/selected-value-prefix.js (100%) rename components/select/src/single-select-a11y/{ => selected-value}/selected-value.js (100%) create mode 100644 components/select/src/single-select-a11y/use-handle-key-press/index.js rename components/select/src/single-select-a11y/{ => use-handle-key-press}/use-handle-key-press.js (67%) create mode 100644 components/select/src/single-select-a11y/use-handle-key-press/use-handle-typing.js create mode 100644 components/select/src/single-select-a11y/use-handle-key-press/use-page-up-down.js diff --git a/components/select/src/single-select-a11y/menu/index.js b/components/select/src/single-select-a11y/menu/index.js new file mode 100644 index 0000000000..bf206853e6 --- /dev/null +++ b/components/select/src/single-select-a11y/menu/index.js @@ -0,0 +1 @@ +export { Menu } from './menu.js' diff --git a/components/select/src/single-select-a11y/menu-filter.js b/components/select/src/single-select-a11y/menu/menu-filter.js similarity index 97% rename from components/select/src/single-select-a11y/menu-filter.js rename to components/select/src/single-select-a11y/menu/menu-filter.js index 4cc2181882..a4ec8102bc 100644 --- a/components/select/src/single-select-a11y/menu-filter.js +++ b/components/select/src/single-select-a11y/menu/menu-filter.js @@ -2,7 +2,7 @@ import { colors, spacers } from '@dhis2/ui-constants' import { Input } from '@dhis2-ui/input' import PropTypes from 'prop-types' import React from 'react' -import i18n from '../locales/index.js' +import i18n from '../../locales/index.js' export function MenuFilter({ value, onChange, dataTest, placeholder, label }) { return ( diff --git a/components/select/src/single-select-a11y/menu-loading.js b/components/select/src/single-select-a11y/menu/menu-loading.js similarity index 100% rename from components/select/src/single-select-a11y/menu-loading.js rename to components/select/src/single-select-a11y/menu/menu-loading.js diff --git a/components/select/src/single-select-a11y/menu-options-list.js b/components/select/src/single-select-a11y/menu/menu-options-list.js similarity index 78% rename from components/select/src/single-select-a11y/menu-options-list.js rename to components/select/src/single-select-a11y/menu/menu-options-list.js index 5dae04aca3..e690721469 100644 --- a/components/select/src/single-select-a11y/menu-options-list.js +++ b/components/select/src/single-select-a11y/menu/menu-options-list.js @@ -1,31 +1,32 @@ import PropTypes from 'prop-types' -import React, { useEffect, useRef } from 'react' -import { isOptionHidden } from './is-option-hidden.js' +import React, { forwardRef, useEffect } from 'react' +import { isOptionHidden } from '../is-option-hidden.js' +import { optionProp } from '../shared-prop-types.js' import { Option } from './option.js' -import { optionsProp } from './shared-prop-types.js' - -export function MenuOptionsList({ - comboBoxId, - expanded, - focussedOptionIndex, - idPrefix, - labelledBy, - options, - selected, - dataTest, - disabled, - loading, - onChange, - onBlur, - onKeyDown, -}) { - const listBoxRef = useRef() +export const MenuOptionsList = forwardRef(function MenuOptionsList( + { + comboBoxId, + expanded, + focussedOptionIndex, + idPrefix, + labelledBy, + options, + selected, + dataTest, + disabled, + loading, + onChange, + onBlur, + onKeyDown, + }, + ref +) { // scrolls the highlighted option into view when: // * the highlighted option changes // * the menu opens useEffect(() => { - const { current: listBox } = listBoxRef + const { current: listBox } = ref const highlightedOption = expanded ? listBox.childNodes[focussedOptionIndex] : null @@ -41,11 +42,11 @@ export function MenuOptionsList({ highlightedOption.scrollIntoView() } } - }, [expanded, focussedOptionIndex]) + }, [expanded, focussedOptionIndex, ref]) return (
) -} +}) MenuOptionsList.propTypes = { comboBoxId: PropTypes.string.isRequired, expanded: PropTypes.bool.isRequired, focussedOptionIndex: PropTypes.number.isRequired, idPrefix: PropTypes.string.isRequired, - options: optionsProp.isRequired, + options: PropTypes.arrayOf(optionProp).isRequired, onChange: PropTypes.func.isRequired, dataTest: PropTypes.string, disabled: PropTypes.bool, diff --git a/components/select/src/single-select-a11y/menu.js b/components/select/src/single-select-a11y/menu/menu.js similarity index 91% rename from components/select/src/single-select-a11y/menu.js rename to components/select/src/single-select-a11y/menu/menu.js index 5a4b49064e..aa52c51293 100644 --- a/components/select/src/single-select-a11y/menu.js +++ b/components/select/src/single-select-a11y/menu/menu.js @@ -4,10 +4,10 @@ import { Popper } from '@dhis2-ui/popper' import cx from 'classnames' import PropTypes from 'prop-types' import React, { useEffect, useState } from 'react' +import { optionProp } from '../shared-prop-types.js' import { MenuFilter } from './menu-filter.js' import { MenuLoading } from './menu-loading.js' import { MenuOptionsList } from './menu-options-list.js' -import { optionsProp } from './shared-prop-types.js' export function Menu({ comboBoxId, @@ -24,6 +24,7 @@ export function Menu({ filterable, hidden, labelledBy, + listBoxRef, loading, loadingText, maxHeight, @@ -66,6 +67,7 @@ export function Menu({ {!options.length &&
{empty}
} (