From 686d8e5be732b8a42b8a0360bc15628ae463f001 Mon Sep 17 00:00:00 2001 From: franciscoemanuel Date: Tue, 19 Oct 2021 02:20:30 -0300 Subject: [PATCH] feat: adds arrow keys navigation on powersearch --- .../hoppscotch-app/components/app/Fuse.vue | 29 +++++++++- .../components/app/PowerSearch.vue | 20 ++++++- .../components/app/PowerSearchEntry.vue | 7 ++- .../helpers/powerSearchNavigation.ts | 54 +++++++++++++++++++ 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 packages/hoppscotch-app/helpers/powerSearchNavigation.ts diff --git a/packages/hoppscotch-app/components/app/Fuse.vue b/packages/hoppscotch-app/components/app/Fuse.vue index ee19a31fb..05358f460 100644 --- a/packages/hoppscotch-app/components/app/Fuse.vue +++ b/packages/hoppscotch-app/components/app/Fuse.vue @@ -4,6 +4,7 @@ v-for="(shortcut, shortcutIndex) in searchResults" :key="`shortcut-${shortcutIndex}`" :ref="`item-${shortcutIndex}`" + :active="shortcutIndex === selectedEntry" :shortcut="shortcut.item" @action="$emit('action', shortcut.item.action)" /> @@ -20,8 +21,15 @@ diff --git a/packages/hoppscotch-app/components/app/PowerSearch.vue b/packages/hoppscotch-app/components/app/PowerSearch.vue index 8825d2bb2..61ced7ff9 100644 --- a/packages/hoppscotch-app/components/app/PowerSearch.vue +++ b/packages/hoppscotch-app/components/app/PowerSearch.vue @@ -47,6 +47,7 @@ v-for="(shortcut, shortcutIndex) in map.shortcuts" :key="`map-${mapIndex}-shortcut-${shortcutIndex}`" :shortcut="shortcut" + :active="shortcutsItems.indexOf(shortcut) === selectedEntry" @action="runAction" /> @@ -56,9 +57,10 @@ diff --git a/packages/hoppscotch-app/components/app/PowerSearchEntry.vue b/packages/hoppscotch-app/components/app/PowerSearchEntry.vue index 497e8b030..62c85c0fb 100644 --- a/packages/hoppscotch-app/components/app/PowerSearchEntry.vue +++ b/packages/hoppscotch-app/components/app/PowerSearchEntry.vue @@ -13,6 +13,7 @@ focus-visible:bg-primaryLight search-entry " + :class="{ active, 'outline-none': active, 'focus-visible': active }" tabindex="0" @click="$emit('action', shortcut.action)" @keydown.enter="$emit('action', shortcut.action)" @@ -26,6 +27,7 @@ group-hover:text-secondaryDark group-hover:opacity-100 group-focus:opacity-100 " + :class="{ 'opacity-100': active, 'text-secondaryDark': active }" :name="shortcut.icon" /> {{ $t(shortcut.label) }} @@ -52,6 +55,7 @@ @@ -73,7 +77,8 @@ defineProps<{ } &:hover::after, - &:focus::after { + &:focus::after, + &.active::after { @apply bg-accentLight; } } diff --git a/packages/hoppscotch-app/helpers/powerSearchNavigation.ts b/packages/hoppscotch-app/helpers/powerSearchNavigation.ts new file mode 100644 index 000000000..02fa6b860 --- /dev/null +++ b/packages/hoppscotch-app/helpers/powerSearchNavigation.ts @@ -0,0 +1,54 @@ +import { ref } from "@nuxtjs/composition-api" + +const NAVIGATION_KEYS = ["ArrowDown", "ArrowUp", "Enter"] + +export function useArrowKeysNavigation(searchItems: any, options: any = {}) { + function handleArrowKeysNavigation( + event: any, + itemIndex: any, + preventPropagation: Boolean + ) { + if (!NAVIGATION_KEYS.includes(event.key)) return + + if (preventPropagation) event.stopImmediatePropagation() + + const itemsLength = searchItems.value.length + const lastItemIndex = itemsLength - 1 + const itemIndexValue = itemIndex.value + const action = searchItems.value[itemIndexValue].action + + if (action && event.key === "Enter" && options.onEnter) { + options.onEnter(action) + return + } + + if (event.key === "ArrowDown") { + itemIndex.value = itemIndexValue < lastItemIndex ? itemIndexValue + 1 : 0 + } else if (itemIndexValue === 0) itemIndex.value = lastItemIndex + else if (event.key === "ArrowUp") itemIndex.value = itemIndexValue - 1 + } + + const preventPropagation = options && options.stopPropagation + + const selectedEntry = ref(0) + + const onKeyUp = (event: any) => { + handleArrowKeysNavigation(event, selectedEntry, preventPropagation) + } + + function bindArrowKeysListerners() { + window.addEventListener("keydown", onKeyUp, { capture: preventPropagation }) + } + + function unbindArrowKeysListerners() { + window.removeEventListener("keydown", onKeyUp, { + capture: preventPropagation, + }) + } + + return { + bindArrowKeysListerners, + unbindArrowKeysListerners, + selectedEntry, + } +}