Skip to content

Commit

Permalink
fix: add arrows navigation for tag hint
Browse files Browse the repository at this point in the history
  • Loading branch information
Antonella Sgarlatta committed Jun 3, 2021
1 parent 622cca7 commit a9f0c6f
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 4 deletions.
37 changes: 36 additions & 1 deletion app/assets/javascripts/components/AutocompleteTagHint.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AppState } from '@/ui_models/app_state';
import { observer } from 'mobx-react-lite';
import { useRef, useEffect } from 'preact/hooks';
import { Icon } from './Icon';

type Props = {
Expand All @@ -9,23 +10,57 @@ type Props = {

export const AutocompleteTagHint = observer(
({ appState, closeOnBlur }: Props) => {
const { autocompleteTagHintFocused } = appState.noteTags;

const hintRef = useRef<HTMLButtonElement>();

const { autocompleteSearchQuery, autocompleteTagResults } =
appState.noteTags;

const onTagHintClick = async () => {
await appState.noteTags.createAndAddNewTag();
};

const onFocus = () => {
appState.noteTags.setAutocompleteTagHintFocused(true);
};

const onBlur = (event: FocusEvent) => {
closeOnBlur(event);
appState.noteTags.setAutocompleteTagHintFocused(false);
};

const onKeyDown = (event: KeyboardEvent) => {
if (event.key === 'ArrowUp') {
if (autocompleteTagResults.length > 0) {
const lastTagResult =
autocompleteTagResults[autocompleteTagResults.length - 1];
appState.noteTags.setFocusedTagResultUuid(lastTagResult.uuid);
} else {
appState.noteTags.setAutocompleteInputFocused(true);
}
}
};

useEffect(() => {
if (autocompleteTagHintFocused) {
hintRef.current.focus();
}
}, [appState.noteTags, autocompleteTagHintFocused]);

return (
<>
{autocompleteTagResults.length > 0 && (
<div className="h-1px my-2 bg-border"></div>
)}
<button
ref={hintRef}
type="button"
className="sn-dropdown-item"
onClick={onTagHintClick}
onBlur={closeOnBlur}
onFocus={onFocus}
onBlur={onBlur}
onKeyDown={onKeyDown}
>
<span>Create new tag:</span>
<span className="bg-contrast rounded text-xs color-text py-1 pl-1 pr-2 flex items-center ml-2">
Expand Down
2 changes: 2 additions & 0 deletions app/assets/javascripts/components/AutocompleteTagInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => {
event.preventDefault();
if (autocompleteTagResults.length > 0) {
appState.noteTags.setFocusedTagResultUuid(autocompleteTagResults[0].uuid);
} else if (autocompleteTagHintVisible) {
appState.noteTags.setAutocompleteTagHintFocused(true);
}
break;
default:
Expand Down
21 changes: 18 additions & 3 deletions app/assets/javascripts/components/AutocompleteTagResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ type Props = {

export const AutocompleteTagResult = observer(
({ appState, tagResult, closeOnBlur }: Props) => {
const { autocompleteSearchQuery, autocompleteTagResults, focusedTagResultUuid } = appState.noteTags;
const {
autocompleteSearchQuery,
autocompleteTagHintVisible,
autocompleteTagResults,
focusedTagResultUuid,
} = appState.noteTags;

const tagResultRef = useRef<HTMLButtonElement>();

Expand All @@ -23,7 +28,10 @@ export const AutocompleteTagResult = observer(
};

const onKeyDown = (event: KeyboardEvent) => {
const tagResultIndex = appState.noteTags.getTagIndex(tagResult, autocompleteTagResults);
const tagResultIndex = appState.noteTags.getTagIndex(
tagResult,
autocompleteTagResults
);
switch (event.key) {
case 'ArrowUp':
event.preventDefault();
Expand All @@ -35,7 +43,14 @@ export const AutocompleteTagResult = observer(
break;
case 'ArrowDown':
event.preventDefault();
appState.noteTags.focusNextTagResult(tagResult);
if (
tagResultIndex === autocompleteTagResults.length - 1 &&
autocompleteTagHintVisible
) {
appState.noteTags.setAutocompleteTagHintFocused(true);
} else {
appState.noteTags.focusNextTagResult(tagResult);
}
break;
default:
return;
Expand Down
7 changes: 7 additions & 0 deletions app/assets/javascripts/ui_models/app_state/note_tags_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { AppState } from './app_state';
export class NoteTagsState {
autocompleteInputFocused = false;
autocompleteSearchQuery = '';
autocompleteTagHintFocused = false;
autocompleteTagResults: SNTag[] = [];
focusedTagResultUuid: UuidString | undefined = undefined;
focusedTagUuid: UuidString | undefined = undefined;
Expand All @@ -20,6 +21,7 @@ export class NoteTagsState {
makeObservable(this, {
autocompleteInputFocused: observable,
autocompleteSearchQuery: observable,
autocompleteTagHintFocused: observable,
autocompleteTagResults: observable,
focusedTagUuid: observable,
focusedTagResultUuid: observable,
Expand All @@ -33,6 +35,7 @@ export class NoteTagsState {
focusPreviousTag: action,
setAutocompleteInputFocused: action,
setAutocompleteSearchQuery: action,
setAutocompleteTagHintFocused: action,
setAutocompleteTagResults: action,
setFocusedTagResultUuid: action,
setFocusedTagUuid: action,
Expand Down Expand Up @@ -69,6 +72,10 @@ export class NoteTagsState {
this.autocompleteSearchQuery = query;
}

setAutocompleteTagHintFocused(focused: boolean): void {
this.autocompleteTagHintFocused = focused;
}

setAutocompleteTagResults(results: SNTag[]): void {
this.autocompleteTagResults = results;
}
Expand Down

0 comments on commit a9f0c6f

Please sign in to comment.