diff --git a/app/assets/javascripts/components/AutocompleteTagHint.tsx b/app/assets/javascripts/components/AutocompleteTagHint.tsx index 00cc04af7..bbb1ec928 100644 --- a/app/assets/javascripts/components/AutocompleteTagHint.tsx +++ b/app/assets/javascripts/components/AutocompleteTagHint.tsx @@ -62,6 +62,7 @@ export const AutocompleteTagHint = observer( onFocus={onFocus} onBlur={onBlur} onKeyDown={onKeyDown} + tabIndex={-1} > Create new tag: diff --git a/app/assets/javascripts/components/AutocompleteTagInput.tsx b/app/assets/javascripts/components/AutocompleteTagInput.tsx index 2dddf3077..80c865f39 100644 --- a/app/assets/javascripts/components/AutocompleteTagInput.tsx +++ b/app/assets/javascripts/components/AutocompleteTagInput.tsx @@ -25,10 +25,10 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { const [dropdownMaxHeight, setDropdownMaxHeight] = useState('auto'); - const dropdownRef = useRef(); + const containerRef = useRef(); const inputRef = useRef(); - const [closeOnBlur] = useCloseOnBlur(dropdownRef, (visible: boolean) => { + const [closeOnBlur] = useCloseOnBlur(containerRef, (visible: boolean) => { setDropdownVisible(visible); appState.noteTags.clearAutocompleteSearch(); }); @@ -69,7 +69,9 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { case 'ArrowDown': event.preventDefault(); if (autocompleteTagResults.length > 0) { - appState.noteTags.setFocusedTagResultUuid(autocompleteTagResults[0].uuid); + appState.noteTags.setFocusedTagResultUuid( + autocompleteTagResults[0].uuid + ); } else if (autocompleteTagHintVisible) { appState.noteTags.setAutocompleteTagHintFocused(true); } @@ -92,54 +94,64 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { useEffect(() => { if (autocompleteInputFocused) { inputRef.current.focus(); - appState.noteTags.setAutocompleteInputFocused(false); } }, [appState.noteTags, autocompleteInputFocused]); return ( - 0 ? 'mt-2' : ''}`} - > - - 0 ? 'w-80' : 'w-70 mr-10'} bg-transparent text-xs + + 0 ? 'mt-2' : ''}`} + > + + 0 ? 'w-80' : 'w-70 mr-10' + } bg-transparent text-xs color-text no-border h-7 focus:outline-none focus:shadow-none focus:border-bottom`} - value={autocompleteSearchQuery} - onChange={onSearchQueryChange} - type="text" - placeholder="Add tag" - onBlur={onBlur} - onFocus={onFocus} - onKeyDown={onKeyDown} - /> - {dropdownVisible && (autocompleteTagResults.length > 0 || autocompleteTagHintVisible) && ( - 0 ? 'w-80' : 'w-70 mr-10'} sn-dropdown flex flex-col py-2 absolute`} - style={{ maxHeight: dropdownMaxHeight, maxWidth: tagsContainerMaxWidth }} - onBlur={closeOnBlur} - > - - {autocompleteTagResults.map((tagResult: SNTag) => ( - - ))} - - {autocompleteTagHintVisible && ( - + value={autocompleteSearchQuery} + onChange={onSearchQueryChange} + type="text" + placeholder="Add tag" + onBlur={onBlur} + onFocus={onFocus} + onKeyDown={onKeyDown} + tabIndex={tags.length === 0 ? 0 : -1} + /> + {dropdownVisible && + (autocompleteTagResults.length > 0 || + autocompleteTagHintVisible) && ( + 0 ? 'w-80' : 'w-70 mr-10' + } sn-dropdown flex flex-col py-2 absolute`} + style={{ + maxHeight: dropdownMaxHeight, + maxWidth: tagsContainerMaxWidth, + }} + onBlur={closeOnBlur} + > + + {autocompleteTagResults.map((tagResult: SNTag) => ( + + ))} + + {autocompleteTagHintVisible && ( + + )} + )} - - )} - - + + + ); }); diff --git a/app/assets/javascripts/components/AutocompleteTagResult.tsx b/app/assets/javascripts/components/AutocompleteTagResult.tsx index 0a7cf9cb8..672d5e72c 100644 --- a/app/assets/javascripts/components/AutocompleteTagResult.tsx +++ b/app/assets/javascripts/components/AutocompleteTagResult.tsx @@ -82,6 +82,7 @@ export const AutocompleteTagResult = observer( onFocus={onFocus} onBlur={onBlur} onKeyDown={onKeyDown} + tabIndex={-1} > diff --git a/app/assets/javascripts/components/NoteTag.tsx b/app/assets/javascripts/components/NoteTag.tsx index f08c94ef8..ba80ebe48 100644 --- a/app/assets/javascripts/components/NoteTag.tsx +++ b/app/assets/javascripts/components/NoteTag.tsx @@ -10,7 +10,7 @@ type Props = { }; export const NoteTag = observer(({ appState, tag }: Props) => { - const { focusedTagUuid, tags } = appState.noteTags; + const { autocompleteInputFocused, focusedTagUuid, tags } = appState.noteTags; const [showDeleteButton, setShowDeleteButton] = useState(false); const [tagClicked, setTagClicked] = useState(false); @@ -51,6 +51,16 @@ export const NoteTag = observer(({ appState, tag }: Props) => { } }; + const getTabIndex = () => { + if (focusedTagUuid) { + return focusedTagUuid === tag.uuid ? 0 : -1; + } + if (autocompleteInputFocused) { + return -1; + } + return tags[0].uuid === tag.uuid ? 0 : -1; + }; + const onKeyDown = (event: KeyboardEvent) => { const tagIndex = appState.noteTags.getTagIndex(tag, tags); switch (event.key) { @@ -75,7 +85,6 @@ export const NoteTag = observer(({ appState, tag }: Props) => { useEffect(() => { if (focusedTagUuid === tag.uuid) { tagRef.current.focus(); - appState.noteTags.setFocusedTagUuid(undefined); } }, [appState.noteTags, focusedTagUuid, tag]); @@ -87,6 +96,7 @@ export const NoteTag = observer(({ appState, tag }: Props) => { onKeyDown={onKeyDown} onFocus={onFocus} onBlur={onBlur} + tabIndex={getTabIndex()} > @@ -99,6 +109,7 @@ export const NoteTag = observer(({ appState, tag }: Props) => { className="ml-2 -mr-1 border-0 p-0 bg-transparent cursor-pointer flex" onBlur={onBlur} onClick={onDeleteTagClick} + tabIndex={-1} >