Skip to content

Commit 98bfd91

Browse files
authored
Merge pull request #674 from lumapps/fix/select-focus-state
fix(select): fix focus state not updating properly
2 parents edc99ef + 8f47adc commit 98bfd91

File tree

3 files changed

+30
-60
lines changed

3 files changed

+30
-60
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
### Fixed
1515

1616
- Fix Select/Dropdown inside Dialog not closing when clicking outside.
17+
- Fix Select focus state not updating correctly.
1718

1819
## [1.0.17][] - 2021-05-27
1920

packages/lumx-react/src/components/select/WithSelectContext.tsx

Lines changed: 3 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { Ref, useCallback, useEffect, useMemo, useRef, useState } from 'react';
1+
import React, { Ref, useCallback, useMemo, useRef } from 'react';
22

33
import classNames from 'classnames';
44
import { uid } from 'uid';
@@ -10,7 +10,7 @@ import { Placement } from '@lumx/react/components/popover/Popover';
1010

1111
import { getRootClassName, handleBasicClasses } from '@lumx/react/utils';
1212
import { mergeRefs } from '@lumx/react/utils/mergeRefs';
13-
13+
import { useListenFocus } from '@lumx/react/hooks/useListenFocus';
1414
import { CoreSelectProps, SelectVariant } from './constants';
1515

1616
/** The display name of the component. */
@@ -25,57 +25,6 @@ export const DEFAULT_PROPS: Partial<CoreSelectProps> = {
2525
variant: SelectVariant.input,
2626
};
2727

28-
/**
29-
* Listen on element focus to store the focus status.
30-
*
31-
* @param element Element to focus.
32-
* @param setIsFocus Setter used to store the focus status of the element.
33-
* @param isOpen Is the list opened
34-
* @param wasBlurred is it blurred
35-
* @param setWasBlurred set blurred
36-
* @param onBlur when its blurred
37-
*/
38-
function useHandleElementFocus(
39-
element: HTMLElement | null,
40-
setIsFocus: (b: boolean) => void,
41-
isOpen: boolean,
42-
wasBlurred: boolean,
43-
setWasBlurred: (b: boolean) => void,
44-
onBlur?: () => void,
45-
) {
46-
useEffect((): VoidFunction | void => {
47-
if (!element) {
48-
return undefined;
49-
}
50-
51-
const setFocus = () => {
52-
if (!isOpen) {
53-
setIsFocus(true);
54-
}
55-
};
56-
57-
const setBlur = () => {
58-
if (!isOpen) {
59-
setIsFocus(false);
60-
61-
if (onBlur) {
62-
onBlur();
63-
}
64-
}
65-
66-
setWasBlurred(true);
67-
};
68-
69-
element.addEventListener('focus', setFocus);
70-
element.addEventListener('blur', setBlur);
71-
72-
return () => {
73-
element.removeEventListener('focus', setFocus);
74-
element.removeEventListener('blur', setBlur);
75-
};
76-
}, [element, isOpen, onBlur, setIsFocus, setWasBlurred, wasBlurred]);
77-
}
78-
7928
export const WithSelectContext = (
8029
SelectElement: React.FC<any>,
8130
{
@@ -94,7 +43,6 @@ export const WithSelectContext = (
9443
isRequired,
9544
isValid,
9645
label,
97-
onBlur,
9846
onClear,
9947
onDropdownClose,
10048
onInfiniteScroll,
@@ -110,10 +58,7 @@ export const WithSelectContext = (
11058
const selectId = useMemo(() => id || `select-${uid()}`, [id]);
11159
const anchorRef = useRef<HTMLElement>(null);
11260
const selectRef = useRef<HTMLDivElement>(null);
113-
const [isFocus, setIsFocus] = useState(Boolean(isOpen));
114-
const [wasBlurred, setWasBlurred] = useState(false);
115-
116-
useHandleElementFocus(anchorRef.current, setIsFocus, Boolean(isOpen), wasBlurred, setWasBlurred, onBlur);
61+
const isFocus = useListenFocus(anchorRef);
11762

11863
const handleKeyboardNav = useCallback(
11964
(evt: React.KeyboardEvent<HTMLElement>) => {
@@ -129,8 +74,6 @@ export const WithSelectContext = (
12974
if (onDropdownClose) {
13075
onDropdownClose();
13176
}
132-
133-
setWasBlurred(false);
13477
anchorRef?.current?.blur();
13578
};
13679

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { RefObject, useEffect, useState } from 'react';
2+
3+
/**
4+
* Listen on element focus to store the focus status.
5+
*/
6+
export function useListenFocus(ref: RefObject<HTMLElement>) {
7+
const [isFocus, setFocus] = useState(false);
8+
9+
useEffect(() => {
10+
const { current: element } = ref;
11+
if (!element) {
12+
return undefined;
13+
}
14+
15+
const onFocus = () => setFocus(true);
16+
const onBlur = () => setFocus(false);
17+
element.addEventListener('focus', onFocus);
18+
element.addEventListener('blur', onBlur);
19+
return () => {
20+
element.removeEventListener('focus', onFocus);
21+
element.removeEventListener('blur', onBlur);
22+
};
23+
}, [ref, setFocus]);
24+
25+
return isFocus;
26+
}

0 commit comments

Comments
 (0)