Skip to content

Commit

Permalink
fix: handling of focus / blur - select open and close
Browse files Browse the repository at this point in the history
  • Loading branch information
abelflopes committed Jul 10, 2024
1 parent 042ea2e commit e150c3c
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 38 deletions.
51 changes: 22 additions & 29 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion packages/components/_provisional/src/dropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export interface DropdownProps {
/** Ref for the root element */
rootRef?: React.MutableRefObject<HTMLDivElement | null>;
onClose?: () => void;
onFocus?: () => void;
onBlur?: () => void;
}

export const Dropdown = ({
Expand All @@ -30,6 +32,8 @@ export const Dropdown = ({
rootRef,
children,
onClose,
onFocus,
onBlur,
}: Readonly<DropdownProps>): React.ReactNode => {
const containerRef = useRef<HTMLElement | null>(null);
const [internalOpen, setInternalOpen] = useState(open);
Expand Down Expand Up @@ -59,8 +63,12 @@ export const Dropdown = ({
if (rootRef) rootRef.current = r;
containerRef.current = r;
}}
tabIndex={0}
role="menu"
style={style}
className={styles.container}>
className={styles.container}
onFocus={onFocus}
onBlur={onBlur}>
<Card skin="shadowed" spacing="none">
<ScrollableContainer
horizontal={false}
Expand Down
25 changes: 17 additions & 8 deletions packages/components/select/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import { getChildrenData, valueAsArray } from "./utils";
import { type SelectProps, type ChangeHandler, type SelectOptionProps } from "./types";
import { SelectContext, type SelectContextProps } from "./context";

// TODO: debounced focus / blur handling in trigger + dropdown wrapper

/**
* Select is a type of input that allows users to choose one or more options from a list of choices.
* The options are hidden by default and revealed when a user interacts with an element. It shows the currently selected option in its default collapsed state.
Expand Down Expand Up @@ -40,6 +38,7 @@ const Select = ({
const selectRef = useRef<HTMLSelectElement>(null);
const rootElRef = useRef<HTMLDivElement>(null);
const dropdownRef = useRef<HTMLDivElement>(null);
const blurTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const [internalValue, setInternalValue] = useState(userValue ?? defaultValue);
const [open, setOpen] = useState(false);
const [search, setSearch] = useState("");
Expand Down Expand Up @@ -77,6 +76,18 @@ const Select = ({
[selectMultiple],
);

const handleFocus = useCallback(() => {
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
setOpen(true);
}, []);

const handleBlur = useCallback(() => {
if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
blurTimeoutRef.current = setTimeout(() => {
setOpen(false);
}, 150);
}, []);

/**
* Handle change events trigger by the user
* Also replicates the event on the native select
Expand Down Expand Up @@ -171,15 +182,11 @@ const Select = ({
tabIndex={0}
className={classNames(styles.root, styles[`skin_${skin}`], className)}
onFocus={(e) => {
setOpen(true);
handleFocus();
onFocus?.(e);
}}
onBlur={(e) => {
if (!selectMultiple) {
setTimeout(() => {
setOpen(false);
}, 100);
}
handleBlur();
onBlur?.(e);
}}>
{selectedValuesList.length > 0 &&
Expand All @@ -198,6 +205,8 @@ const Select = ({
spacing="s"
rootRef={dropdownRef}
excludeAutoPosition={["left", "right", "start", "end", "full"]}
onFocus={handleFocus}
onBlur={handleBlur}
onClose={() => {
setOpen(false);
}}>
Expand Down

0 comments on commit e150c3c

Please sign in to comment.