Skip to content

Commit b4c14f5

Browse files
committed
Use arrow keys to select models
1 parent 549c752 commit b4c14f5

File tree

1 file changed

+54
-7
lines changed

1 file changed

+54
-7
lines changed

src/lib/components/InferencePlayground/InferencePlaygroundModelSelectorModal.svelte

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script lang="ts">
22
import type { ModelEntryWithTokenizer } from "./types";
33
4-
import { createEventDispatcher } from "svelte";
4+
import { createEventDispatcher, tick } from "svelte";
55
66
import { FEATUED_MODELS_IDS } from "./inferencePlaygroundUtils";
77
import IconSearch from "../Icons/IconSearch.svelte";
@@ -11,14 +11,51 @@
1111
1212
let backdropEl: HTMLDivElement;
1313
let query = "";
14+
let highlightIdx = 0;
15+
let ignoreCursorHighlight = false;
16+
let containerEl: HTMLDivElement;
1417
1518
const dispatch = createEventDispatcher<{ modelSelected: string; close: void }>();
1619
1720
function handleKeydown(event: KeyboardEvent) {
1821
const { key } = event;
22+
let scrollLogicalPosition: ScrollLogicalPosition = "end";
1923
if (key === "Escape") {
2024
event.preventDefault();
2125
dispatch("close");
26+
} else if (key === "Enter") {
27+
const searchEls = (containerEl.firstChild?.childNodes ?? []) as HTMLAnchorElement[];
28+
searchEls?.[highlightIdx].click();
29+
} else if (key === "ArrowUp") {
30+
event.preventDefault();
31+
highlightIdx--;
32+
scrollLogicalPosition = "start";
33+
ignoreCursorHighlight = true;
34+
} else if (key === "ArrowDown") {
35+
event.preventDefault();
36+
highlightIdx++;
37+
ignoreCursorHighlight = true;
38+
}
39+
const n = models.length;
40+
highlightIdx = ((highlightIdx % n) + n) % n;
41+
scrollToResult(scrollLogicalPosition);
42+
}
43+
44+
async function scrollToResult(block: ScrollLogicalPosition) {
45+
await tick();
46+
const highlightedEl = document.querySelector(".highlighted");
47+
if (containerEl && highlightedEl) {
48+
const { bottom: containerBottom, top: containerTop } = containerEl.getBoundingClientRect();
49+
const { bottom: highlightedBottom, top: highlightedTop } = highlightedEl.getBoundingClientRect();
50+
if (highlightedBottom > containerBottom || containerTop > highlightedTop) {
51+
highlightedEl.scrollIntoView({ block });
52+
}
53+
}
54+
}
55+
56+
function highlightRow(idx: number) {
57+
if (!ignoreCursorHighlight) {
58+
highlightIdx = idx;
2259
}
2360
}
2461
@@ -43,15 +80,18 @@
4380
);
4481
</script>
4582

46-
<svelte:window on:keydown={handleKeydown} />
83+
<svelte:window on:keydown={handleKeydown} on:mousemove={() => (ignoreCursorHighlight = false)} />
4784

4885
<div
4986
class="fixed inset-0 z-10 flex h-screen items-start justify-center bg-black/85 pt-32"
5087
bind:this={backdropEl}
5188
on:click|stopPropagation={handleBackdropClick}
5289
>
5390
<div class="flex w-full max-w-[600px] items-start justify-center p-10">
54-
<div class="flex h-full w-full flex-col overflow-hidden rounded-lg border bg-white text-gray-900 shadow-md">
91+
<div
92+
class="flex h-full w-full flex-col overflow-hidden rounded-lg border bg-white text-gray-900 shadow-md"
93+
bind:this={containerEl}
94+
>
5595
<div class="flex items-center border-b px-3">
5696
<IconSearch classNames="mr-2 text-sm" />
5797
<input
@@ -65,10 +105,13 @@
65105
<div class="p-1">
66106
<div class="px-2 py-1.5 text-xs font-medium text-gray-500">Trending</div>
67107
<div>
68-
{#each featuredModels as model}
108+
{#each featuredModels as model, idx}
69109
{@const [nameSpace, modelName] = model.id.split("/")}
70110
<button
71-
class="flex w-full cursor-pointer items-center px-2 py-1.5 text-sm hover:bg-gray-100"
111+
class="flex w-full cursor-pointer items-center px-2 py-1.5 text-sm {highlightIdx === idx
112+
? 'highlighted bg-gray-100'
113+
: ''}"
114+
on:mouseenter={() => highlightRow(idx)}
72115
on:click={() => {
73116
dispatch("modelSelected", model.id);
74117
dispatch("close");
@@ -88,10 +131,14 @@
88131
<div class="p-1">
89132
<div class="px-2 py-1.5 text-xs font-medium text-gray-500">Other Models</div>
90133
<div>
91-
{#each otherModels as model}
134+
{#each otherModels as model, _idx}
92135
{@const [nameSpace, modelName] = model.id.split("/")}
136+
{@const idx = featuredModels.length + _idx}
93137
<button
94-
class="flex w-full cursor-pointer items-center px-2 py-1.5 text-sm hover:bg-gray-100"
138+
class="flex w-full cursor-pointer items-center px-2 py-1.5 text-sm {highlightIdx === idx
139+
? 'highlighted bg-gray-100'
140+
: ''}"
141+
on:mouseenter={() => highlightRow(idx)}
95142
on:click={() => {
96143
dispatch("modelSelected", model.id);
97144
dispatch("close");

0 commit comments

Comments
 (0)