feat: Improve prompt picker keyboard navigation

This commit is contained in:
Aleksander Grygier 2026-02-05 17:15:31 +01:00
parent c5fa3634bc
commit 5fe03b2bdc
4 changed files with 35 additions and 6 deletions

View File

@ -270,8 +270,8 @@
if (event.key === KeyboardKey.ARROW_DOWN) {
event.preventDefault();
if (selectedIndex < filteredPrompts.length - 1) {
selectedIndex++;
if (filteredPrompts.length > 0) {
selectedIndex = (selectedIndex + 1) % filteredPrompts.length;
}
return true;
@ -279,8 +279,8 @@
if (event.key === KeyboardKey.ARROW_UP) {
event.preventDefault();
if (selectedIndex > 0) {
selectedIndex--;
if (filteredPrompts.length > 0) {
selectedIndex = selectedIndex === 0 ? filteredPrompts.length - 1 : selectedIndex - 1;
}
return true;

View File

@ -27,6 +27,24 @@
getServerLabel,
onPromptClick
}: Props = $props();
let listContainer = $state<HTMLDivElement | null>(null);
$effect(() => {
if (listContainer && selectedIndex >= 0 && selectedIndex < prompts.length) {
const selectedElement = listContainer.querySelector(
`[data-prompt-index="${selectedIndex}"]`
) as HTMLElement;
if (selectedElement) {
selectedElement.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'nearest'
});
}
}
});
</script>
<ScrollArea>
@ -36,7 +54,7 @@
</div>
{/if}
<div class="max-h-64 p-2" class:pt-13={showSearchInput}>
<div bind:this={listContainer} class="max-h-64 p-2" class:pt-13={showSearchInput}>
{#if isLoading}
<ChatFormPromptPickerListItemSkeleton />
{:else if prompts.length === 0}
@ -49,6 +67,7 @@
{@const serverLabel = server ? getServerLabel(server) : prompt.serverName}
<ChatFormPromptPickerListItem
data-prompt-index={index}
{prompt}
{server}
{serverLabel}

View File

@ -8,13 +8,22 @@
serverLabel: string;
isSelected?: boolean;
onClick: () => void;
'data-prompt-index'?: number;
}
let { prompt, server, serverLabel, isSelected = false, onClick }: Props = $props();
let {
prompt,
server,
serverLabel,
isSelected = false,
onClick,
'data-prompt-index': dataPromptIndex
}: Props = $props();
</script>
<button
type="button"
data-prompt-index={dataPromptIndex}
onclick={onClick}
class="flex w-full cursor-pointer items-start gap-3 rounded-lg px-3 py-2 text-left hover:bg-accent/50 {isSelected
? 'bg-accent/50'

View File

@ -44,6 +44,7 @@
'aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40',
className
)}
style="backdrop-filter: blur(0.5rem);"
{type}
bind:value
{...restProps}