Skip to content

Commit

Permalink
feat(Select): default arrow key handling to focus items
Browse files Browse the repository at this point in the history
  • Loading branch information
adamviktora committed Oct 23, 2024
1 parent f19a7a5 commit c036179
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 0 deletions.
19 changes: 19 additions & 0 deletions packages/react-core/src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export interface SelectProps extends MenuProps, OUIAProps {
onOpenChange?: (isOpen: boolean) => void;
/** Keys that trigger onOpenChange, defaults to tab and escape. It is highly recommended to include Escape in the array, while Tab may be omitted if the menu contains non-menu items that are focusable. */
onOpenChangeKeys?: string[];
/** Custom callback to override the default behaviour when pressing up/down arrows. Defaults to navigating through the menu items (with focus on them). */
onArrowUpDownKeyPress?: (event: KeyboardEvent) => void;
/** Indicates if the select should be without the outer box-shadow */
isPlain?: boolean;
/** @hide Forwarded ref */
Expand Down Expand Up @@ -95,6 +97,7 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
shouldFocusFirstItemOnOpen = false,
onOpenChange,
onOpenChangeKeys = ['Escape', 'Tab'],
onArrowUpDownKeyPress,
isPlain,
innerRef,
zIndex = 9999,
Expand Down Expand Up @@ -131,6 +134,18 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
}, [isOpen]);

React.useEffect(() => {
const onArrowUpDownKeyPressDefault = (event: KeyboardEvent) => {
event.preventDefault();

const firstItemSelector = 'li button:not(:disabled),li input:not(:disabled)';
const lastItemSelector = 'li:last-child button:not(:disabled),li:last-child input:not(:disabled)';

const elementToFocus = menuRef?.current?.querySelector(
event.key === 'ArrowDown' ? firstItemSelector : lastItemSelector
);
elementToFocus && (elementToFocus as HTMLElement).focus();
};

const handleMenuKeys = (event: KeyboardEvent) => {
// Close the menu on tab or escape if onOpenChange is provided
if (
Expand All @@ -144,6 +159,10 @@ const SelectBase: React.FunctionComponent<SelectProps & OUIAProps> = ({
toggleRef.current?.focus();
}
}

if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
onArrowUpDownKeyPress ? onArrowUpDownKeyPress(event) : onArrowUpDownKeyPressDefault(event);
}
};

const handleClick = (event: MouseEvent) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ export const SelectTypeahead: React.FunctionComponent = () => {
onOpenChange={(isOpen) => {
!isOpen && closeMenu();
}}
onArrowUpDownKeyPress={(_event) => {}}
toggle={toggle}
shouldFocusFirstItemOnOpen={false}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ export const TypeaheadSelectBase: React.FunctionComponent<TypeaheadSelectProps>
onOpenChange={(isOpen) => {
!isOpen && closeMenu();
}}
onArrowUpDownKeyPress={(_event) => {}}
toggle={toggle}
shouldFocusFirstItemOnOpen={false}
ref={innerRef}
Expand Down

0 comments on commit c036179

Please sign in to comment.