if (menuRef.current) { const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); firstElement && firstElement.focus(); } }; /** reopen the menu if it's closed and any un-designated keys are hit */ const handleDefault = () => { if (!menuIsOpen) { setMenuIsOpen(true); } }; /** enable keyboard only usage while focused on the text input */ const handleTextInputKeyDown = (event: React.KeyboardEvent) => { switch (event.key) { case 'Enter': handleEnter(); break; case 'Escape': handleEscape(); break; case 'Tab': handleTab(); break; case 'ArrowUp': case 'ArrowDown': handleArrowKey(); break; default: handleDefault(); } }; /** apply focus to the text input */ const focusTextInput = () => { textInputGroupRef.current.querySelector('input').focus(); }; /** add the text of the selected item as a new chip */ const onSelect = (event: React.MouseEvent, _itemId: string | number) => { const selectedText = (event.target as HTMLElement).innerText; addChip(selectedText); event.stopPropagation(); focusTextInput(); }; /** close the menu when a click occurs outside of the menu or text input group */ const handleClick = (event: MouseEvent) => { if ( menuRef.current && !menuRef.current.contains(event.target as HTMLElement) && !textInputGroupRef.current.contains(event.target as HTMLElement) ) { setMenuIsOpen(false); } }; /** enable keyboard only usage while focused on the menu */ const handleMenuKeyDown = (event: React.KeyboardEvent) => { switch (event.key) { case 'Tab': case 'Escape': event.preventDefault(); focusTextInput(); setMenuIsOpen(false); break; case 'Enter': case ' ': setTimeout(() => setMenuIsOpen(false), 0); break; } }; /** show the search icon only when there are no chips to prevent the chips from being displayed behind the icon */ const showSearchIcon = !currentChips.length; /** only show the clear button when there is something that can be cleared */ const showClearButton = !!inputValue || !!currentChips.length; /** render the utilities component only when a component it contains is being rendered */ const showUtilities = showClearButton; const inputGroup = (
} value={inputValue} hint={hint} onChange={handleInputChange} onFocus={() => setMenuIsOpen(true)} onKeyDown={handleTextInputKeyDown} placeholder="search" aria-label="Search input" > {currentChips.map((currentChip) => ( deleteChip(currentChip)}> {currentChip} ))} {showUtilities && ( {showClearButton && (
} /> )} )}
); const menu = (
{menuItems}
); return ( textInputGroupRef.current} isVisible={menuIsOpen} onDocumentClick={handleClick} /> ); };