From 0fe487ae03906fdf7e397cbee9836318ca0c782c Mon Sep 17 00:00:00 2001 From: adamviktora Date: Wed, 23 Oct 2024 18:18:41 +0200 Subject: [PATCH 1/8] feat(Select): default arrow key handling to focus items --- .../src/components/Select/Select.tsx | 30 +++++++++++++++++++ .../Select/examples/SelectMultiTypeahead.tsx | 2 +- .../examples/SelectMultiTypeaheadCheckbox.tsx | 2 +- .../SelectMultiTypeaheadCreatable.tsx | 2 +- .../Select/examples/SelectTypeahead.tsx | 2 +- .../examples/SelectTypeaheadCreatable.tsx | 2 +- .../Select/MultiTypeaheadSelect.tsx | 2 +- .../src/components/Select/TypeaheadSelect.tsx | 2 +- 8 files changed, 37 insertions(+), 7 deletions(-) diff --git a/packages/react-core/src/components/Select/Select.tsx b/packages/react-core/src/components/Select/Select.tsx index ace74b9eeb1..982892f2a19 100644 --- a/packages/react-core/src/components/Select/Select.tsx +++ b/packages/react-core/src/components/Select/Select.tsx @@ -62,6 +62,10 @@ 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. Default is focusing the menu items (first item on arrow down, last item on arrow up). */ + onArrowUpDownKeyDown?: (event: KeyboardEvent) => void; + /** Indicates that the Select is used as a typeahead (combobox). Focus won't shift to menu items when pressing up/down arrows. */ + isTypeahead?: boolean; /** Indicates if the select should be without the outer box-shadow */ isPlain?: boolean; /** @hide Forwarded ref */ @@ -95,6 +99,8 @@ const SelectBase: React.FunctionComponent = ({ shouldFocusFirstItemOnOpen = false, onOpenChange, onOpenChangeKeys = ['Escape', 'Tab'], + onArrowUpDownKeyDown, + isTypeahead, isPlain, innerRef, zIndex = 9999, @@ -131,6 +137,21 @@ const SelectBase: React.FunctionComponent = ({ }, [isOpen]); React.useEffect(() => { + const onArrowUpDownKeyDownDefault = (event: KeyboardEvent) => { + event.preventDefault(); + + let listItem: HTMLLIElement; + if (event.key === 'ArrowDown') { + listItem = menuRef.current?.querySelector('li'); + } else { + const allItems = menuRef.current?.querySelectorAll('li'); + listItem = allItems ? allItems[allItems.length - 1] : null; + } + + const focusableElement = listItem?.querySelector('button:not(:disabled),input:not(:disabled)'); + focusableElement && (focusableElement as HTMLElement).focus(); + }; + const handleMenuKeys = (event: KeyboardEvent) => { // Close the menu on tab or escape if onOpenChange is provided if ( @@ -144,6 +165,14 @@ const SelectBase: React.FunctionComponent = ({ toggleRef.current?.focus(); } } + + if (event.key === 'ArrowDown' || event.key === 'ArrowUp') { + if (onArrowUpDownKeyDown) { + onArrowUpDownKeyDown(event); + } else if (!isTypeahead) { + onArrowUpDownKeyDownDefault(event); + } + } }; const handleClick = (event: MouseEvent) => { @@ -168,6 +197,7 @@ const SelectBase: React.FunctionComponent = ({ toggleRef, onOpenChange, onOpenChangeKeys, + onArrowUpDownKeyDown, shouldPreventScrollOnItemFocus, shouldFocusFirstItemOnOpen, focusTimeoutDelay diff --git a/packages/react-core/src/components/Select/examples/SelectMultiTypeahead.tsx b/packages/react-core/src/components/Select/examples/SelectMultiTypeahead.tsx index 41707fd1136..2ee90fd6460 100644 --- a/packages/react-core/src/components/Select/examples/SelectMultiTypeahead.tsx +++ b/packages/react-core/src/components/Select/examples/SelectMultiTypeahead.tsx @@ -247,7 +247,7 @@ export const SelectMultiTypeahead: React.FunctionComponent = () => { !isOpen && closeMenu(); }} toggle={toggle} - shouldFocusFirstItemOnOpen={false} + isTypeahead > {selectOptions.map((option, index) => ( diff --git a/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCheckbox.tsx b/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCheckbox.tsx index 030b62cc93b..fb22d42ac97 100644 --- a/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCheckbox.tsx +++ b/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCheckbox.tsx @@ -241,7 +241,7 @@ export const SelectMultiTypeaheadCheckbox: React.FunctionComponent = () => { !isOpen && closeMenu(); }} toggle={toggle} - shouldFocusFirstItemOnOpen={false} + isTypeahead > {selectOptions.map((option, index) => ( diff --git a/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCreatable.tsx b/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCreatable.tsx index e43c1afe1dd..e7906e1ceef 100644 --- a/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCreatable.tsx +++ b/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCreatable.tsx @@ -260,7 +260,7 @@ export const SelectMultiTypeaheadCreatable: React.FunctionComponent = () => { !isOpen && closeMenu(); }} toggle={toggle} - shouldFocusFirstItemOnOpen={false} + isTypeahead > {selectOptions.map((option, index) => ( diff --git a/packages/react-core/src/components/Select/examples/SelectTypeahead.tsx b/packages/react-core/src/components/Select/examples/SelectTypeahead.tsx index 12ca075992d..4562dd901c6 100644 --- a/packages/react-core/src/components/Select/examples/SelectTypeahead.tsx +++ b/packages/react-core/src/components/Select/examples/SelectTypeahead.tsx @@ -244,7 +244,7 @@ export const SelectTypeahead: React.FunctionComponent = () => { !isOpen && closeMenu(); }} toggle={toggle} - shouldFocusFirstItemOnOpen={false} + isTypeahead > {selectOptions.map((option, index) => ( diff --git a/packages/react-core/src/components/Select/examples/SelectTypeaheadCreatable.tsx b/packages/react-core/src/components/Select/examples/SelectTypeaheadCreatable.tsx index fda4f11bdfd..fa8ad00ff71 100644 --- a/packages/react-core/src/components/Select/examples/SelectTypeaheadCreatable.tsx +++ b/packages/react-core/src/components/Select/examples/SelectTypeaheadCreatable.tsx @@ -251,7 +251,7 @@ export const SelectTypeaheadCreatable: React.FunctionComponent = () => { !isOpen && closeMenu(); }} toggle={toggle} - shouldFocusFirstItemOnOpen={false} + isTypeahead > {selectOptions.map((option, index) => ( diff --git a/packages/react-templates/src/components/Select/MultiTypeaheadSelect.tsx b/packages/react-templates/src/components/Select/MultiTypeaheadSelect.tsx index 5beb2b9d7b5..0895a5d60bd 100644 --- a/packages/react-templates/src/components/Select/MultiTypeaheadSelect.tsx +++ b/packages/react-templates/src/components/Select/MultiTypeaheadSelect.tsx @@ -320,7 +320,7 @@ export const MultiTypeaheadSelectBase: React.FunctionComponent diff --git a/packages/react-templates/src/components/Select/TypeaheadSelect.tsx b/packages/react-templates/src/components/Select/TypeaheadSelect.tsx index b674a227d5d..64d96621880 100644 --- a/packages/react-templates/src/components/Select/TypeaheadSelect.tsx +++ b/packages/react-templates/src/components/Select/TypeaheadSelect.tsx @@ -361,7 +361,7 @@ export const TypeaheadSelectBase: React.FunctionComponent !isOpen && closeMenu(); }} toggle={toggle} - shouldFocusFirstItemOnOpen={false} + isTypeahead ref={innerRef} {...props} > From 039e09536aac7bcf00f67dda67131aca4523763b Mon Sep 17 00:00:00 2001 From: adamviktora Date: Fri, 25 Oct 2024 17:57:01 +0200 Subject: [PATCH 2/8] feat(Dropdown): default arrow key handling to focus items --- .../src/components/Dropdown/Dropdown.tsx | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/packages/react-core/src/components/Dropdown/Dropdown.tsx b/packages/react-core/src/components/Dropdown/Dropdown.tsx index 00c13f9782a..66a9597cb96 100644 --- a/packages/react-core/src/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/components/Dropdown/Dropdown.tsx @@ -51,6 +51,8 @@ export interface DropdownProps 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. Default is focusing the menu items (first item on arrow down, last item on arrow up). */ + onArrowUpDownKeyDown?: (event: KeyboardEvent) => void; /** Indicates if the menu should be without the outer box-shadow. */ isPlain?: boolean; /** Indicates if the menu should be scrollable. */ @@ -85,6 +87,7 @@ const DropdownBase: React.FunctionComponent = ({ toggle, shouldFocusToggleOnSelect = false, onOpenChange, + onArrowUpDownKeyDown, isPlain, isScrollable, innerRef, @@ -127,6 +130,23 @@ const DropdownBase: React.FunctionComponent = ({ }, [isOpen]); React.useEffect(() => { + const onArrowUpDownKeyDownDefault = (event: KeyboardEvent) => { + event.preventDefault(); + + let listItem: HTMLLIElement; + if (event.key === 'ArrowDown') { + listItem = menuRef.current?.querySelector('li'); + } else { + const allItems = menuRef.current?.querySelectorAll('li'); + listItem = allItems ? allItems[allItems.length - 1] : null; + } + + const focusableElement = listItem?.querySelector( + 'button:not(:disabled),input:not(:disabled),a:not([aria-disabled="true"])' + ); + focusableElement && (focusableElement as HTMLElement).focus(); + }; + const handleMenuKeys = (event: KeyboardEvent) => { // Close the menu on tab or escape if onOpenChange is provided if ( @@ -139,6 +159,14 @@ const DropdownBase: React.FunctionComponent = ({ toggleRef.current?.focus(); } } + + if (event.key === 'ArrowDown' || event.key === 'ArrowUp') { + if (onArrowUpDownKeyDown) { + onArrowUpDownKeyDown(event); + } else { + onArrowUpDownKeyDownDefault(event); + } + } }; const handleClick = (event: MouseEvent) => { @@ -163,6 +191,7 @@ const DropdownBase: React.FunctionComponent = ({ toggleRef, onOpenChange, onOpenChangeKeys, + onArrowUpDownKeyDown, shouldPreventScrollOnItemFocus, shouldFocusFirstItemOnOpen, focusTimeoutDelay From fd712a75ded6649ffa3df8eec5a816d7e38cc382 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Fri, 25 Oct 2024 17:57:27 +0200 Subject: [PATCH 3/8] feat(MenuContainer): default arrow key handling to focus items --- .../src/components/Menu/MenuContainer.tsx | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/react-core/src/components/Menu/MenuContainer.tsx b/packages/react-core/src/components/Menu/MenuContainer.tsx index c1b96273b90..103346ccce8 100644 --- a/packages/react-core/src/components/Menu/MenuContainer.tsx +++ b/packages/react-core/src/components/Menu/MenuContainer.tsx @@ -17,6 +17,7 @@ export interface MenuPopperProps { /** Flag to prevent the popper from overflowing its container and becoming partially obscured. */ preventOverflow?: boolean; } + export interface MenuContainerProps { /** Menu to be rendered */ menu: React.ReactElement>; @@ -33,6 +34,8 @@ export interface MenuContainerProps { 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. Default is focusing the menu items (first item on arrow down, last item on arrow up). */ + onArrowUpDownKeyDown?: (event: KeyboardEvent) => void; /** z-index of the dropdown menu */ zIndex?: number; /** Additional properties to pass to the Popper */ @@ -55,10 +58,11 @@ export const MenuContainer: React.FunctionComponent = ({ toggle, toggleRef, onOpenChange, + onArrowUpDownKeyDown, zIndex = 9999, popperProps, onOpenChangeKeys = ['Escape', 'Tab'], - shouldFocusFirstItemOnOpen = true, + shouldFocusFirstItemOnOpen = false, shouldPreventScrollOnItemFocus = true, focusTimeoutDelay = 0 }: MenuContainerProps) => { @@ -79,6 +83,23 @@ export const MenuContainer: React.FunctionComponent = ({ }, [isOpen]); React.useEffect(() => { + const onArrowUpDownKeyDownDefault = (event: KeyboardEvent) => { + event.preventDefault(); + + let listItem: HTMLLIElement; + if (event.key === 'ArrowDown') { + listItem = menuRef.current?.querySelector('li'); + } else { + const allItems = menuRef.current?.querySelectorAll('li'); + listItem = allItems ? allItems[allItems.length - 1] : null; + } + + const focusableElement = listItem?.querySelector( + 'button:not(:disabled),input:not(:disabled),a:not([aria-disabled="true"])' + ); + focusableElement && (focusableElement as HTMLElement).focus(); + }; + const handleMenuKeys = (event: KeyboardEvent) => { // Close the menu on tab or escape if onOpenChange is provided if ( @@ -90,6 +111,14 @@ export const MenuContainer: React.FunctionComponent = ({ toggleRef.current?.focus(); } } + + if (event.key === 'ArrowDown' || event.key === 'ArrowUp') { + if (onArrowUpDownKeyDown) { + onArrowUpDownKeyDown(event); + } else { + onArrowUpDownKeyDownDefault(event); + } + } }; const handleClick = (event: MouseEvent) => { @@ -108,7 +137,16 @@ export const MenuContainer: React.FunctionComponent = ({ window.removeEventListener('keydown', handleMenuKeys); window.removeEventListener('click', handleClick); }; - }, [focusTimeoutDelay, isOpen, menuRef, onOpenChange, onOpenChangeKeys, shouldPreventScrollOnItemFocus, toggleRef]); + }, [ + focusTimeoutDelay, + isOpen, + menuRef, + onOpenChange, + onOpenChangeKeys, + onArrowUpDownKeyDown, + shouldPreventScrollOnItemFocus, + toggleRef + ]); return ( Date: Tue, 29 Oct 2024 16:56:48 +0100 Subject: [PATCH 4/8] fix: invoke callback only when toggle is focused and menu opened --- .../src/components/Dropdown/Dropdown.tsx | 22 +++++++++++-------- .../src/components/Menu/MenuContainer.tsx | 22 +++++++++++-------- .../src/components/Select/Select.tsx | 22 +++++++++++-------- 3 files changed, 39 insertions(+), 27 deletions(-) diff --git a/packages/react-core/src/components/Dropdown/Dropdown.tsx b/packages/react-core/src/components/Dropdown/Dropdown.tsx index 66a9597cb96..c9a1c05b7d2 100644 --- a/packages/react-core/src/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/components/Dropdown/Dropdown.tsx @@ -51,8 +51,8 @@ export interface DropdownProps 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. Default is focusing the menu items (first item on arrow down, last item on arrow up). */ - onArrowUpDownKeyDown?: (event: KeyboardEvent) => void; + /** Callback to override the default behavior when pressing up/down arrow keys when the toggle has focus and the menu is open. By default non-disabled menu items will receive focus - the first item on arrow down or the last item on arrow up. */ + onToggleArrowKeydown?: (event: KeyboardEvent) => void; /** Indicates if the menu should be without the outer box-shadow. */ isPlain?: boolean; /** Indicates if the menu should be scrollable. */ @@ -87,7 +87,7 @@ const DropdownBase: React.FunctionComponent = ({ toggle, shouldFocusToggleOnSelect = false, onOpenChange, - onArrowUpDownKeyDown, + onToggleArrowKeydown, isPlain, isScrollable, innerRef, @@ -130,7 +130,7 @@ const DropdownBase: React.FunctionComponent = ({ }, [isOpen]); React.useEffect(() => { - const onArrowUpDownKeyDownDefault = (event: KeyboardEvent) => { + const onToggleArrowKeydownDefault = (event: KeyboardEvent) => { event.preventDefault(); let listItem: HTMLLIElement; @@ -160,11 +160,15 @@ const DropdownBase: React.FunctionComponent = ({ } } - if (event.key === 'ArrowDown' || event.key === 'ArrowUp') { - if (onArrowUpDownKeyDown) { - onArrowUpDownKeyDown(event); + if ( + isOpen && + toggleRef.current?.contains(event.target as Node) && + (event.key === 'ArrowDown' || event.key === 'ArrowUp') + ) { + if (onToggleArrowKeydown) { + onToggleArrowKeydown(event); } else { - onArrowUpDownKeyDownDefault(event); + onToggleArrowKeydownDefault(event); } } }; @@ -191,7 +195,7 @@ const DropdownBase: React.FunctionComponent = ({ toggleRef, onOpenChange, onOpenChangeKeys, - onArrowUpDownKeyDown, + onToggleArrowKeydown, shouldPreventScrollOnItemFocus, shouldFocusFirstItemOnOpen, focusTimeoutDelay diff --git a/packages/react-core/src/components/Menu/MenuContainer.tsx b/packages/react-core/src/components/Menu/MenuContainer.tsx index 103346ccce8..2825d6e5b18 100644 --- a/packages/react-core/src/components/Menu/MenuContainer.tsx +++ b/packages/react-core/src/components/Menu/MenuContainer.tsx @@ -34,8 +34,8 @@ export interface MenuContainerProps { 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. Default is focusing the menu items (first item on arrow down, last item on arrow up). */ - onArrowUpDownKeyDown?: (event: KeyboardEvent) => void; + /** Callback to override the default behavior when pressing up/down arrow keys when the toggle has focus and the menu is open. By default non-disabled menu items will receive focus - the first item on arrow down or the last item on arrow up. */ + onToggleArrowKeydown?: (event: KeyboardEvent) => void; /** z-index of the dropdown menu */ zIndex?: number; /** Additional properties to pass to the Popper */ @@ -58,7 +58,7 @@ export const MenuContainer: React.FunctionComponent = ({ toggle, toggleRef, onOpenChange, - onArrowUpDownKeyDown, + onToggleArrowKeydown, zIndex = 9999, popperProps, onOpenChangeKeys = ['Escape', 'Tab'], @@ -83,7 +83,7 @@ export const MenuContainer: React.FunctionComponent = ({ }, [isOpen]); React.useEffect(() => { - const onArrowUpDownKeyDownDefault = (event: KeyboardEvent) => { + const onToggleArrowKeydownDefault = (event: KeyboardEvent) => { event.preventDefault(); let listItem: HTMLLIElement; @@ -112,11 +112,15 @@ export const MenuContainer: React.FunctionComponent = ({ } } - if (event.key === 'ArrowDown' || event.key === 'ArrowUp') { - if (onArrowUpDownKeyDown) { - onArrowUpDownKeyDown(event); + if ( + isOpen && + toggleRef.current?.contains(event.target as Node) && + (event.key === 'ArrowDown' || event.key === 'ArrowUp') + ) { + if (onToggleArrowKeydown) { + onToggleArrowKeydown(event); } else { - onArrowUpDownKeyDownDefault(event); + onToggleArrowKeydownDefault(event); } } }; @@ -143,7 +147,7 @@ export const MenuContainer: React.FunctionComponent = ({ menuRef, onOpenChange, onOpenChangeKeys, - onArrowUpDownKeyDown, + onToggleArrowKeydown, shouldPreventScrollOnItemFocus, toggleRef ]); diff --git a/packages/react-core/src/components/Select/Select.tsx b/packages/react-core/src/components/Select/Select.tsx index 982892f2a19..7b3b9176fb1 100644 --- a/packages/react-core/src/components/Select/Select.tsx +++ b/packages/react-core/src/components/Select/Select.tsx @@ -62,8 +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. Default is focusing the menu items (first item on arrow down, last item on arrow up). */ - onArrowUpDownKeyDown?: (event: KeyboardEvent) => void; + /** Callback to override the default behavior when pressing up/down arrow keys when the toggle has focus and the menu is open. By default non-disabled menu items will receive focus - the first item on arrow down or the last item on arrow up. */ + onToggleArrowKeydown?: (event: KeyboardEvent) => void; /** Indicates that the Select is used as a typeahead (combobox). Focus won't shift to menu items when pressing up/down arrows. */ isTypeahead?: boolean; /** Indicates if the select should be without the outer box-shadow */ @@ -99,7 +99,7 @@ const SelectBase: React.FunctionComponent = ({ shouldFocusFirstItemOnOpen = false, onOpenChange, onOpenChangeKeys = ['Escape', 'Tab'], - onArrowUpDownKeyDown, + onToggleArrowKeydown, isTypeahead, isPlain, innerRef, @@ -137,7 +137,7 @@ const SelectBase: React.FunctionComponent = ({ }, [isOpen]); React.useEffect(() => { - const onArrowUpDownKeyDownDefault = (event: KeyboardEvent) => { + const onToggleArrowKeydownDefault = (event: KeyboardEvent) => { event.preventDefault(); let listItem: HTMLLIElement; @@ -166,11 +166,15 @@ const SelectBase: React.FunctionComponent = ({ } } - if (event.key === 'ArrowDown' || event.key === 'ArrowUp') { - if (onArrowUpDownKeyDown) { - onArrowUpDownKeyDown(event); + if ( + isOpen && + toggleRef.current?.contains(event.target as Node) && + (event.key === 'ArrowDown' || event.key === 'ArrowUp') + ) { + if (onToggleArrowKeydown) { + onToggleArrowKeydown(event); } else if (!isTypeahead) { - onArrowUpDownKeyDownDefault(event); + onToggleArrowKeydownDefault(event); } } }; @@ -197,7 +201,7 @@ const SelectBase: React.FunctionComponent = ({ toggleRef, onOpenChange, onOpenChangeKeys, - onArrowUpDownKeyDown, + onToggleArrowKeydown, shouldPreventScrollOnItemFocus, shouldFocusFirstItemOnOpen, focusTimeoutDelay From 513c6f5db321310fe508a36ff169ba789e677f69 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Tue, 12 Nov 2024 14:17:52 +0100 Subject: [PATCH 5/8] fix: query selector, refactor common functionality --- .../src/components/Dropdown/Dropdown.tsx | 27 +++---------------- .../src/components/Menu/MenuContainer.tsx | 27 +++---------------- .../src/components/Select/Select.tsx | 25 +++-------------- .../src/helpers/KeyboardHandler.tsx | 27 +++++++++++++++++++ 4 files changed, 36 insertions(+), 70 deletions(-) diff --git a/packages/react-core/src/components/Dropdown/Dropdown.tsx b/packages/react-core/src/components/Dropdown/Dropdown.tsx index c9a1c05b7d2..4e85e8d5f57 100644 --- a/packages/react-core/src/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/components/Dropdown/Dropdown.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { css } from '@patternfly/react-styles'; import { Menu, MenuContent, MenuProps } from '../Menu'; import { Popper } from '../../helpers/Popper/Popper'; -import { useOUIAProps, OUIAProps } from '../../helpers'; +import { useOUIAProps, OUIAProps, onToggleArrowKeydownDefault } from '../../helpers'; export interface DropdownPopperProps { /** Vertical direction of the popper. If enableFlip is set to true, this will set the initial direction before the popper flips. */ @@ -130,23 +130,6 @@ const DropdownBase: React.FunctionComponent = ({ }, [isOpen]); React.useEffect(() => { - const onToggleArrowKeydownDefault = (event: KeyboardEvent) => { - event.preventDefault(); - - let listItem: HTMLLIElement; - if (event.key === 'ArrowDown') { - listItem = menuRef.current?.querySelector('li'); - } else { - const allItems = menuRef.current?.querySelectorAll('li'); - listItem = allItems ? allItems[allItems.length - 1] : null; - } - - const focusableElement = listItem?.querySelector( - 'button:not(:disabled),input:not(:disabled),a:not([aria-disabled="true"])' - ); - focusableElement && (focusableElement as HTMLElement).focus(); - }; - const handleMenuKeys = (event: KeyboardEvent) => { // Close the menu on tab or escape if onOpenChange is provided if ( @@ -160,15 +143,11 @@ const DropdownBase: React.FunctionComponent = ({ } } - if ( - isOpen && - toggleRef.current?.contains(event.target as Node) && - (event.key === 'ArrowDown' || event.key === 'ArrowUp') - ) { + if (isOpen && toggleRef.current?.contains(event.target as Node)) { if (onToggleArrowKeydown) { onToggleArrowKeydown(event); } else { - onToggleArrowKeydownDefault(event); + onToggleArrowKeydownDefault(event, menuRef); } } }; diff --git a/packages/react-core/src/components/Menu/MenuContainer.tsx b/packages/react-core/src/components/Menu/MenuContainer.tsx index 2825d6e5b18..f2cc336dc58 100644 --- a/packages/react-core/src/components/Menu/MenuContainer.tsx +++ b/packages/react-core/src/components/Menu/MenuContainer.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Popper } from '../../helpers/Popper/Popper'; +import { onToggleArrowKeydownDefault, Popper } from '../../helpers'; export interface MenuPopperProps { /** Vertical direction of the popper. If enableFlip is set to true, this will set the initial direction before the popper flips. */ @@ -83,23 +83,6 @@ export const MenuContainer: React.FunctionComponent = ({ }, [isOpen]); React.useEffect(() => { - const onToggleArrowKeydownDefault = (event: KeyboardEvent) => { - event.preventDefault(); - - let listItem: HTMLLIElement; - if (event.key === 'ArrowDown') { - listItem = menuRef.current?.querySelector('li'); - } else { - const allItems = menuRef.current?.querySelectorAll('li'); - listItem = allItems ? allItems[allItems.length - 1] : null; - } - - const focusableElement = listItem?.querySelector( - 'button:not(:disabled),input:not(:disabled),a:not([aria-disabled="true"])' - ); - focusableElement && (focusableElement as HTMLElement).focus(); - }; - const handleMenuKeys = (event: KeyboardEvent) => { // Close the menu on tab or escape if onOpenChange is provided if ( @@ -112,15 +95,11 @@ export const MenuContainer: React.FunctionComponent = ({ } } - if ( - isOpen && - toggleRef.current?.contains(event.target as Node) && - (event.key === 'ArrowDown' || event.key === 'ArrowUp') - ) { + if (isOpen && toggleRef.current?.contains(event.target as Node)) { if (onToggleArrowKeydown) { onToggleArrowKeydown(event); } else { - onToggleArrowKeydownDefault(event); + onToggleArrowKeydownDefault(event, menuRef); } } }; diff --git a/packages/react-core/src/components/Select/Select.tsx b/packages/react-core/src/components/Select/Select.tsx index 7b3b9176fb1..2e4d224fd7d 100644 --- a/packages/react-core/src/components/Select/Select.tsx +++ b/packages/react-core/src/components/Select/Select.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { css } from '@patternfly/react-styles'; import { Menu, MenuContent, MenuProps } from '../Menu'; import { Popper } from '../../helpers/Popper/Popper'; -import { getOUIAProps, OUIAProps, getDefaultOUIAId } from '../../helpers'; +import { getOUIAProps, OUIAProps, getDefaultOUIAId, onToggleArrowKeydownDefault } from '../../helpers'; export interface SelectPopperProps { /** Vertical direction of the popper. If enableFlip is set to true, this will set the initial direction before the popper flips. */ @@ -137,21 +137,6 @@ const SelectBase: React.FunctionComponent = ({ }, [isOpen]); React.useEffect(() => { - const onToggleArrowKeydownDefault = (event: KeyboardEvent) => { - event.preventDefault(); - - let listItem: HTMLLIElement; - if (event.key === 'ArrowDown') { - listItem = menuRef.current?.querySelector('li'); - } else { - const allItems = menuRef.current?.querySelectorAll('li'); - listItem = allItems ? allItems[allItems.length - 1] : null; - } - - const focusableElement = listItem?.querySelector('button:not(:disabled),input:not(:disabled)'); - focusableElement && (focusableElement as HTMLElement).focus(); - }; - const handleMenuKeys = (event: KeyboardEvent) => { // Close the menu on tab or escape if onOpenChange is provided if ( @@ -166,15 +151,11 @@ const SelectBase: React.FunctionComponent = ({ } } - if ( - isOpen && - toggleRef.current?.contains(event.target as Node) && - (event.key === 'ArrowDown' || event.key === 'ArrowUp') - ) { + if (isOpen && toggleRef.current?.contains(event.target as Node)) { if (onToggleArrowKeydown) { onToggleArrowKeydown(event); } else if (!isTypeahead) { - onToggleArrowKeydownDefault(event); + onToggleArrowKeydownDefault(event, menuRef); } } }; diff --git a/packages/react-core/src/helpers/KeyboardHandler.tsx b/packages/react-core/src/helpers/KeyboardHandler.tsx index afdaf7b5fb0..f2ffe5af172 100644 --- a/packages/react-core/src/helpers/KeyboardHandler.tsx +++ b/packages/react-core/src/helpers/KeyboardHandler.tsx @@ -176,6 +176,33 @@ export const setTabIndex = (options: HTMLElement[]) => { } }; +/** + * This function is used in Dropdown, Select and MenuContainer as a default toggle keydown behavior. When the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key. + * + * @param event Event triggered by the keyboard + * @param menuRef Menu reference + */ +export const onToggleArrowKeydownDefault = (event: KeyboardEvent, menuRef: React.RefObject) => { + if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') { + return; + } + + event.preventDefault(); + + const interactiveElementSelector = 'button:not(:disabled),input:not(:disabled),a:not([aria-disabled="true"])'; + const listItemSelector = `li:has(${interactiveElementSelector})`; + let listItem: Element; + if (event.key === 'ArrowDown') { + listItem = menuRef.current?.querySelector(listItemSelector); + } else { + const allItems = menuRef.current?.querySelectorAll(listItemSelector); + listItem = allItems ? allItems[allItems.length - 1] : null; + } + + const focusableElement = listItem?.querySelector(interactiveElementSelector); + focusableElement && (focusableElement as HTMLElement).focus(); +}; + class KeyboardHandler extends React.Component { static displayName = 'KeyboardHandler'; static defaultProps: KeyboardHandlerProps = { From cdd6f0f692bdee924ee7001933a79636f9e9f748 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Tue, 12 Nov 2024 14:27:04 +0100 Subject: [PATCH 6/8] feat: use general onToggleKeydown instead of onToggleArrowKeydown --- .../src/components/Dropdown/Dropdown.tsx | 16 ++++++++-------- .../src/components/Menu/MenuContainer.tsx | 16 ++++++++-------- .../react-core/src/components/Select/Select.tsx | 16 ++++++++-------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/packages/react-core/src/components/Dropdown/Dropdown.tsx b/packages/react-core/src/components/Dropdown/Dropdown.tsx index 4e85e8d5f57..c556937a095 100644 --- a/packages/react-core/src/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/components/Dropdown/Dropdown.tsx @@ -51,8 +51,8 @@ export interface DropdownProps 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[]; - /** Callback to override the default behavior when pressing up/down arrow keys when the toggle has focus and the menu is open. By default non-disabled menu items will receive focus - the first item on arrow down or the last item on arrow up. */ - onToggleArrowKeydown?: (event: KeyboardEvent) => void; + /** Callback to override the toggle keydown behavior. By default, when the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key. */ + onToggleKeydown?: (event: KeyboardEvent) => void; /** Indicates if the menu should be without the outer box-shadow. */ isPlain?: boolean; /** Indicates if the menu should be scrollable. */ @@ -87,7 +87,7 @@ const DropdownBase: React.FunctionComponent = ({ toggle, shouldFocusToggleOnSelect = false, onOpenChange, - onToggleArrowKeydown, + onToggleKeydown, isPlain, isScrollable, innerRef, @@ -143,10 +143,10 @@ const DropdownBase: React.FunctionComponent = ({ } } - if (isOpen && toggleRef.current?.contains(event.target as Node)) { - if (onToggleArrowKeydown) { - onToggleArrowKeydown(event); - } else { + if (toggleRef.current?.contains(event.target as Node)) { + if (onToggleKeydown) { + onToggleKeydown(event); + } else if (isOpen) { onToggleArrowKeydownDefault(event, menuRef); } } @@ -174,7 +174,7 @@ const DropdownBase: React.FunctionComponent = ({ toggleRef, onOpenChange, onOpenChangeKeys, - onToggleArrowKeydown, + onToggleKeydown, shouldPreventScrollOnItemFocus, shouldFocusFirstItemOnOpen, focusTimeoutDelay diff --git a/packages/react-core/src/components/Menu/MenuContainer.tsx b/packages/react-core/src/components/Menu/MenuContainer.tsx index f2cc336dc58..888e7c7dbe4 100644 --- a/packages/react-core/src/components/Menu/MenuContainer.tsx +++ b/packages/react-core/src/components/Menu/MenuContainer.tsx @@ -34,8 +34,8 @@ export interface MenuContainerProps { 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[]; - /** Callback to override the default behavior when pressing up/down arrow keys when the toggle has focus and the menu is open. By default non-disabled menu items will receive focus - the first item on arrow down or the last item on arrow up. */ - onToggleArrowKeydown?: (event: KeyboardEvent) => void; + /** Callback to override the toggle keydown behavior. By default, when the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key. */ + onToggleKeydown?: (event: KeyboardEvent) => void; /** z-index of the dropdown menu */ zIndex?: number; /** Additional properties to pass to the Popper */ @@ -58,7 +58,7 @@ export const MenuContainer: React.FunctionComponent = ({ toggle, toggleRef, onOpenChange, - onToggleArrowKeydown, + onToggleKeydown, zIndex = 9999, popperProps, onOpenChangeKeys = ['Escape', 'Tab'], @@ -95,10 +95,10 @@ export const MenuContainer: React.FunctionComponent = ({ } } - if (isOpen && toggleRef.current?.contains(event.target as Node)) { - if (onToggleArrowKeydown) { - onToggleArrowKeydown(event); - } else { + if (toggleRef.current?.contains(event.target as Node)) { + if (onToggleKeydown) { + onToggleKeydown(event); + } else if (isOpen) { onToggleArrowKeydownDefault(event, menuRef); } } @@ -126,7 +126,7 @@ export const MenuContainer: React.FunctionComponent = ({ menuRef, onOpenChange, onOpenChangeKeys, - onToggleArrowKeydown, + onToggleKeydown, shouldPreventScrollOnItemFocus, toggleRef ]); diff --git a/packages/react-core/src/components/Select/Select.tsx b/packages/react-core/src/components/Select/Select.tsx index 2e4d224fd7d..74f943a7e25 100644 --- a/packages/react-core/src/components/Select/Select.tsx +++ b/packages/react-core/src/components/Select/Select.tsx @@ -62,8 +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[]; - /** Callback to override the default behavior when pressing up/down arrow keys when the toggle has focus and the menu is open. By default non-disabled menu items will receive focus - the first item on arrow down or the last item on arrow up. */ - onToggleArrowKeydown?: (event: KeyboardEvent) => void; + /** Callback to override the toggle keydown behavior. By default, when the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key. */ + onToggleKeydown?: (event: KeyboardEvent) => void; /** Indicates that the Select is used as a typeahead (combobox). Focus won't shift to menu items when pressing up/down arrows. */ isTypeahead?: boolean; /** Indicates if the select should be without the outer box-shadow */ @@ -99,7 +99,7 @@ const SelectBase: React.FunctionComponent = ({ shouldFocusFirstItemOnOpen = false, onOpenChange, onOpenChangeKeys = ['Escape', 'Tab'], - onToggleArrowKeydown, + onToggleKeydown, isTypeahead, isPlain, innerRef, @@ -151,10 +151,10 @@ const SelectBase: React.FunctionComponent = ({ } } - if (isOpen && toggleRef.current?.contains(event.target as Node)) { - if (onToggleArrowKeydown) { - onToggleArrowKeydown(event); - } else if (!isTypeahead) { + if (toggleRef.current?.contains(event.target as Node)) { + if (onToggleKeydown) { + onToggleKeydown(event); + } else if (isOpen && !isTypeahead) { onToggleArrowKeydownDefault(event, menuRef); } } @@ -182,7 +182,7 @@ const SelectBase: React.FunctionComponent = ({ toggleRef, onOpenChange, onOpenChangeKeys, - onToggleArrowKeydown, + onToggleKeydown, shouldPreventScrollOnItemFocus, shouldFocusFirstItemOnOpen, focusTimeoutDelay From de4472124f4225cf5fa798725048bbea5e3e0bec Mon Sep 17 00:00:00 2001 From: adamviktora Date: Tue, 12 Nov 2024 15:06:25 +0100 Subject: [PATCH 7/8] refactor(onToggleArrowKeydownDefault): don't use :has() selector --- .../react-core/src/helpers/KeyboardHandler.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/react-core/src/helpers/KeyboardHandler.tsx b/packages/react-core/src/helpers/KeyboardHandler.tsx index f2ffe5af172..716e0703098 100644 --- a/packages/react-core/src/helpers/KeyboardHandler.tsx +++ b/packages/react-core/src/helpers/KeyboardHandler.tsx @@ -189,17 +189,17 @@ export const onToggleArrowKeydownDefault = (event: KeyboardEvent, menuRef: React event.preventDefault(); - const interactiveElementSelector = 'button:not(:disabled),input:not(:disabled),a:not([aria-disabled="true"])'; - const listItemSelector = `li:has(${interactiveElementSelector})`; - let listItem: Element; + const listItems = Array.from(menuRef.current?.querySelectorAll('li')); + const focusableElements = listItems + .map((li) => li.querySelector('button:not(:disabled),input:not(:disabled),a:not([aria-disabled="true"])')) + .filter((el) => el !== null); + + let focusableElement: Element; if (event.key === 'ArrowDown') { - listItem = menuRef.current?.querySelector(listItemSelector); + focusableElement = focusableElements[0]; } else { - const allItems = menuRef.current?.querySelectorAll(listItemSelector); - listItem = allItems ? allItems[allItems.length - 1] : null; + focusableElement = focusableElements[focusableElements.length - 1]; } - - const focusableElement = listItem?.querySelector(interactiveElementSelector); focusableElement && (focusableElement as HTMLElement).focus(); }; From 901e606b0b66d54997c5bc7c5bbb0aac76dc9ac8 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Wed, 20 Nov 2024 11:51:39 +0100 Subject: [PATCH 8/8] fix: remove isTypeahead prop in favor of variant --- packages/react-core/src/components/Select/Select.tsx | 8 ++++---- .../components/Select/examples/SelectMultiTypeahead.tsx | 2 +- .../Select/examples/SelectMultiTypeaheadCheckbox.tsx | 2 +- .../Select/examples/SelectMultiTypeaheadCreatable.tsx | 2 +- .../src/components/Select/examples/SelectTypeahead.tsx | 2 +- .../Select/examples/SelectTypeaheadCreatable.tsx | 2 +- .../src/components/Select/MultiTypeaheadSelect.tsx | 2 +- .../src/components/Select/TypeaheadSelect.tsx | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/react-core/src/components/Select/Select.tsx b/packages/react-core/src/components/Select/Select.tsx index 74f943a7e25..604881bf862 100644 --- a/packages/react-core/src/components/Select/Select.tsx +++ b/packages/react-core/src/components/Select/Select.tsx @@ -64,8 +64,8 @@ export interface SelectProps extends MenuProps, OUIAProps { onOpenChangeKeys?: string[]; /** Callback to override the toggle keydown behavior. By default, when the toggle has focus and the menu is open, pressing the up/down arrow keys will focus a valid non-disabled menu item - the first item for the down arrow key and last item for the up arrow key. */ onToggleKeydown?: (event: KeyboardEvent) => void; - /** Indicates that the Select is used as a typeahead (combobox). Focus won't shift to menu items when pressing up/down arrows. */ - isTypeahead?: boolean; + /** Select variant. For typeahead variant focus won't shift to menu items when pressing up/down arrows. */ + variant?: 'default' | 'typeahead'; /** Indicates if the select should be without the outer box-shadow */ isPlain?: boolean; /** @hide Forwarded ref */ @@ -100,7 +100,7 @@ const SelectBase: React.FunctionComponent = ({ onOpenChange, onOpenChangeKeys = ['Escape', 'Tab'], onToggleKeydown, - isTypeahead, + variant, isPlain, innerRef, zIndex = 9999, @@ -154,7 +154,7 @@ const SelectBase: React.FunctionComponent = ({ if (toggleRef.current?.contains(event.target as Node)) { if (onToggleKeydown) { onToggleKeydown(event); - } else if (isOpen && !isTypeahead) { + } else if (isOpen && variant !== 'typeahead') { onToggleArrowKeydownDefault(event, menuRef); } } diff --git a/packages/react-core/src/components/Select/examples/SelectMultiTypeahead.tsx b/packages/react-core/src/components/Select/examples/SelectMultiTypeahead.tsx index 2ee90fd6460..e4a1538a0ca 100644 --- a/packages/react-core/src/components/Select/examples/SelectMultiTypeahead.tsx +++ b/packages/react-core/src/components/Select/examples/SelectMultiTypeahead.tsx @@ -247,7 +247,7 @@ export const SelectMultiTypeahead: React.FunctionComponent = () => { !isOpen && closeMenu(); }} toggle={toggle} - isTypeahead + variant="typeahead" > {selectOptions.map((option, index) => ( diff --git a/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCheckbox.tsx b/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCheckbox.tsx index fb22d42ac97..2b46979959f 100644 --- a/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCheckbox.tsx +++ b/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCheckbox.tsx @@ -241,7 +241,7 @@ export const SelectMultiTypeaheadCheckbox: React.FunctionComponent = () => { !isOpen && closeMenu(); }} toggle={toggle} - isTypeahead + variant="typeahead" > {selectOptions.map((option, index) => ( diff --git a/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCreatable.tsx b/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCreatable.tsx index e7906e1ceef..256a7ee7afb 100644 --- a/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCreatable.tsx +++ b/packages/react-core/src/components/Select/examples/SelectMultiTypeaheadCreatable.tsx @@ -260,7 +260,7 @@ export const SelectMultiTypeaheadCreatable: React.FunctionComponent = () => { !isOpen && closeMenu(); }} toggle={toggle} - isTypeahead + variant="typeahead" > {selectOptions.map((option, index) => ( diff --git a/packages/react-core/src/components/Select/examples/SelectTypeahead.tsx b/packages/react-core/src/components/Select/examples/SelectTypeahead.tsx index 4562dd901c6..e682de837fa 100644 --- a/packages/react-core/src/components/Select/examples/SelectTypeahead.tsx +++ b/packages/react-core/src/components/Select/examples/SelectTypeahead.tsx @@ -244,7 +244,7 @@ export const SelectTypeahead: React.FunctionComponent = () => { !isOpen && closeMenu(); }} toggle={toggle} - isTypeahead + variant="typeahead" > {selectOptions.map((option, index) => ( diff --git a/packages/react-core/src/components/Select/examples/SelectTypeaheadCreatable.tsx b/packages/react-core/src/components/Select/examples/SelectTypeaheadCreatable.tsx index fa8ad00ff71..bd6cf9a3f8b 100644 --- a/packages/react-core/src/components/Select/examples/SelectTypeaheadCreatable.tsx +++ b/packages/react-core/src/components/Select/examples/SelectTypeaheadCreatable.tsx @@ -251,7 +251,7 @@ export const SelectTypeaheadCreatable: React.FunctionComponent = () => { !isOpen && closeMenu(); }} toggle={toggle} - isTypeahead + variant="typeahead" > {selectOptions.map((option, index) => ( diff --git a/packages/react-templates/src/components/Select/MultiTypeaheadSelect.tsx b/packages/react-templates/src/components/Select/MultiTypeaheadSelect.tsx index 0895a5d60bd..552b4594d51 100644 --- a/packages/react-templates/src/components/Select/MultiTypeaheadSelect.tsx +++ b/packages/react-templates/src/components/Select/MultiTypeaheadSelect.tsx @@ -320,7 +320,7 @@ export const MultiTypeaheadSelectBase: React.FunctionComponent diff --git a/packages/react-templates/src/components/Select/TypeaheadSelect.tsx b/packages/react-templates/src/components/Select/TypeaheadSelect.tsx index 64d96621880..b0e14b5282b 100644 --- a/packages/react-templates/src/components/Select/TypeaheadSelect.tsx +++ b/packages/react-templates/src/components/Select/TypeaheadSelect.tsx @@ -361,7 +361,7 @@ export const TypeaheadSelectBase: React.FunctionComponent !isOpen && closeMenu(); }} toggle={toggle} - isTypeahead + variant="typeahead" ref={innerRef} {...props} >