enh: search input arrow controls

This commit is contained in:
Timothy Jaeryang Baek 2025-05-20 23:47:41 +04:00
parent b78354100f
commit 6121d4696a
2 changed files with 42 additions and 5 deletions

View File

@ -26,6 +26,8 @@
let searchDebounceTimeout;
let selectedIdx = 0;
const searchHandler = async () => {
console.log('search', query);
@ -89,25 +91,47 @@
on:input={searchHandler}
placeholder={$i18n.t('Search')}
showClearButton={true}
onKeydown={(e) => {
console.log('e', e);
if (e.code === 'Enter' && (chatList ?? []).length > 0) {
const item = document.querySelector(`[data-arrow-selected="true"]`);
if (item) {
item?.click();
}
show = false;
return;
} else if (e.code === 'ArrowDown') {
selectedIdx = Math.min(selectedIdx + 1, (chatList ?? []).length - 1);
} else if (e.code === 'ArrowUp') {
selectedIdx = Math.max(selectedIdx - 1, 0);
} else {
selectedIdx = 0;
}
const item = document.querySelector(`[data-arrow-selected="true"]`);
item?.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'instant' });
}}
/>
</div>
<!-- <hr class="border-gray-100 dark:border-gray-850 my-1" /> -->
<div class="flex flex-col overflow-y-auto h-80 scrollbar-hidden px-5 pb-1">
<div class="flex flex-col overflow-y-auto h-80 scrollbar-hidden px-3 pb-1">
{#if chatList}
{#if chatList.length === 0}
<div class="text-xs text-gray-500 dark:text-gray-400 text-center">
<div class="text-xs text-gray-500 dark:text-gray-400 text-center px-5">
{$i18n.t('No results found')}
</div>
{/if}
{#each chatList as chat, idx}
{#each chatList as chat, idx (chat.id)}
{#if idx === 0 || (idx > 0 && chat.time_range !== chatList[idx - 1].time_range)}
<div
class="w-full text-xs text-gray-500 dark:text-gray-500 font-medium {idx === 0
? ''
: 'pt-5'} pb-2"
: 'pt-5'} pb-2 px-2"
>
{$i18n.t(chat.time_range)}
<!-- localisation keys for time_range to be recognized from the i18next parser (so they don't get automatically removed):
@ -132,9 +156,16 @@
{/if}
<a
class=" w-full flex justify-between items-center rounded-lg text-sm py-1 px-1 my-1"
class=" w-full flex justify-between items-center rounded-lg text-sm py-2 px-3 hover:bg-gray-50 dark:hover:bg-gray-850 {selectedIdx ===
idx
? 'bg-gray-50 dark:bg-gray-850'
: ''}"
href="/c/{chat.id}"
draggable="false"
data-arrow-selected={selectedIdx === idx ? 'true' : undefined}
on:mouseenter={() => {
selectedIdx = idx;
}}
on:click={() => {
show = false;
onClose();

View File

@ -11,6 +11,7 @@
export let placeholder = '';
export let value = '';
export let showClearButton = false;
export let onKeydown = (e) => {};
let selectedIdx = 0;
@ -145,6 +146,10 @@
// if the user types something, reset to the top selection.
selectedIdx = 0;
}
if (!document.getElementById('search-options-container')) {
onKeydown(e);
}
}}
/>
@ -164,6 +169,7 @@
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="absolute top-0 mt-8 left-0 right-1 border border-gray-100 dark:border-gray-900 bg-gray-50 dark:bg-gray-950 rounded-lg z-10 shadow-lg"
id="search-options-container"
in:fade={{ duration: 50 }}
on:mouseenter={() => {
selectedIdx = null;