From ff4ab7866fc6a4cd4b23744010eabdd2b370dded Mon Sep 17 00:00:00 2001 From: Mirlan Date: Wed, 17 Feb 2021 17:38:13 +0600 Subject: [PATCH] Ott 833 user acc select country (#304) * fix(817): a11y fix * fix(833): country selection in user account --- src/features/Combobox/hooks/index.tsx | 35 +++++++++++-------- src/features/Combobox/index.tsx | 2 +- src/features/Combobox/styled.tsx | 5 ++- .../UserSubscriptionsList/styled.tsx | 10 ++++-- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/features/Combobox/hooks/index.tsx b/src/features/Combobox/hooks/index.tsx index 353db0c3..a74344be 100644 --- a/src/features/Combobox/hooks/index.tsx +++ b/src/features/Combobox/hooks/index.tsx @@ -1,4 +1,9 @@ -import type { ChangeEvent, KeyboardEvent } from 'react' +import type { + FocusEvent, + ChangeEvent, + KeyboardEvent, + BaseSyntheticEvent, +} from 'react' import { useState, useCallback, @@ -10,7 +15,6 @@ import toLower from 'lodash/toLower' import find from 'lodash/find' import trim from 'lodash/trim' import size from 'lodash/size' -import isEmpty from 'lodash/isEmpty' import { useToggle } from 'hooks' @@ -18,6 +22,10 @@ import type { Props, Option } from '../types' import { matchSort } from '../helpers' import { useKeyboardScroll } from './useKeyboardScroll' +const isOptionClicked = (target: HTMLElement | null) => ( + target?.getAttribute('role') === 'option' +) + const useQuery = ({ onChange, value }: Props) => { const [query, setQuery] = useState('') @@ -72,7 +80,8 @@ export const useCombobox = (props: Props) => { ) || null ), [options]) - const onOptionSelect = useCallback((option: string) => { + const onOptionSelect = useCallback((option: string, e?: BaseSyntheticEvent) => { + e?.stopPropagation() const selectedOption = findOptionByName(option) setQuery(selectedOption?.name || '') onSelect?.(selectedOption) @@ -85,20 +94,18 @@ export const useCombobox = (props: Props) => { ]) const onOutsideClick = (event: MouseEvent) => { - if (event.target !== inputFieldRef.current as HTMLInputElement) { - close() - if (results[0]?.name.includes(query) && query) { - onOptionSelect(results[0].name) - } else { - onOptionSelect(query) - } + if (event.target !== inputFieldRef.current) { + onOptionSelect(query) } } - const onInputBlur = () => { - if (isEmpty(results)) { - onOptionSelect('') - } + const onInputBlur = (event: FocusEvent) => { + const target = event.relatedTarget as HTMLElement | null + // клик по элементу списка тоже вызывает onBlur + // если кликали элемент списка то событие обрабатывает onOptionSelect + if (isOptionClicked(target)) return + + onOptionSelect(query) } useEffect(() => { diff --git a/src/features/Combobox/index.tsx b/src/features/Combobox/index.tsx index c387bf2c..38c30fde 100644 --- a/src/features/Combobox/index.tsx +++ b/src/features/Combobox/index.tsx @@ -94,7 +94,7 @@ export const Combobox = (props: Props) => { > {map(options, (option, i) => ( onOptionSelect(option.name)} + onClick={(e) => onOptionSelect(option.name, e)} aria-selected={index === i} isHighlighted={index === i} key={option.id} diff --git a/src/features/Combobox/styled.tsx b/src/features/Combobox/styled.tsx index 8508df7e..2df01bc7 100644 --- a/src/features/Combobox/styled.tsx +++ b/src/features/Combobox/styled.tsx @@ -22,7 +22,10 @@ export const PopOver = styled.ul` ${customStylesMixin}; ` -export const ListOption = styled.li<{isHighlighted?: boolean}>` +export const ListOption = styled.li.attrs(() => ({ + role: 'option', + tabIndex: 0, +}))<{isHighlighted?: boolean}>` width: 100%; height: 48px; font-size: 16px; diff --git a/src/features/UserAccount/components/UserSubscriptionsList/styled.tsx b/src/features/UserAccount/components/UserSubscriptionsList/styled.tsx index 04d49916..6dc7e351 100644 --- a/src/features/UserAccount/components/UserSubscriptionsList/styled.tsx +++ b/src/features/UserAccount/components/UserSubscriptionsList/styled.tsx @@ -58,7 +58,9 @@ export const ActionsWrapper = styled.div` } ` -export const Subscription = styled.div` +export const Subscription = styled.div.attrs(() => ({ + tabIndex: 0, +}))` width: 800px; height: 70px; display: flex; @@ -70,8 +72,10 @@ export const Subscription = styled.div` border-radius: 2px; overflow: hidden; - :hover ${ActionsWrapper} { - transform: translateX(0); + :focus-within, :hover { + ${ActionsWrapper} { + transform: translateX(0); + } } `