diff --git a/src/features/gifPicker/components/GifPickerHeader.tsx b/src/features/gifPicker/components/GifPickerHeader.tsx index 19d56cbad0..3b979a15a7 100644 --- a/src/features/gifPicker/components/GifPickerHeader.tsx +++ b/src/features/gifPicker/components/GifPickerHeader.tsx @@ -9,65 +9,87 @@ import * as TextField from '#/components/forms/TextField' import {ArrowLeft_Stroke2_Corner0_Rounded as Arrow} from '#/components/icons/Arrow' import {MagnifyingGlass_Stroke2_Corner0_Rounded as Search} from '#/components/icons/MagnifyingGlass' import {IS_WEB} from '#/env' +import { + GIF_AUTOCOMPLETE_LISTBOX_ID, + GifAutocompleteSuggestions, + suggestionItemId, +} from '#/features/gifPicker/components/GifAutocompleteSuggestions' +import {type GifAutocompleteState} from '#/features/gifPicker/hooks/useGifAutocomplete' export function GifPickerHeader({ inputRef, onChangeText, onClose, onEscape, + autocomplete, }: { inputRef: Ref onChangeText: (text: string) => void onClose: () => void onEscape: () => void + autocomplete: GifAutocompleteState }) { const {_} = useLingui() const t = useTheme() const {gtMobile} = useBreakpoints() return ( - - {!gtMobile && IS_WEB && ( - - )} + + + {!gtMobile && IS_WEB && ( + + )} - - - { - if (nativeEvent.key === 'Escape') { - onEscape() + + + { + if (nativeEvent.key === 'Escape') { + if (!autocomplete.handleKeyDown('Escape')) { + onEscape() + } + } else { + autocomplete.handleKeyDown(nativeEvent.key) + } + }} + // @ts-ignore web-only ARIA props + role={autocomplete.isVisible ? 'combobox' : undefined} + aria-controls={ + autocomplete.isVisible ? GIF_AUTOCOMPLETE_LISTBOX_ID : undefined } - }} - /> - + aria-expanded={autocomplete.isVisible} + aria-autocomplete={autocomplete.isVisible ? 'list' : undefined} + aria-activedescendant={ + autocomplete.isVisible && autocomplete.activeIndex >= 0 + ? suggestionItemId(autocomplete.activeIndex) + : undefined + } + /> + + - {/* future: tabs (Trending / Recents / Categories) render here */} + {autocomplete.isVisible && ( + + )} ) }