mirror of
https://github.com/open-webui/open-webui
synced 2025-06-26 18:26:48 +00:00
enh: search input arrow controls
This commit is contained in:
parent
b78354100f
commit
6121d4696a
@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
let searchDebounceTimeout;
|
let searchDebounceTimeout;
|
||||||
|
|
||||||
|
let selectedIdx = 0;
|
||||||
|
|
||||||
const searchHandler = async () => {
|
const searchHandler = async () => {
|
||||||
console.log('search', query);
|
console.log('search', query);
|
||||||
|
|
||||||
@ -89,25 +91,47 @@
|
|||||||
on:input={searchHandler}
|
on:input={searchHandler}
|
||||||
placeholder={$i18n.t('Search')}
|
placeholder={$i18n.t('Search')}
|
||||||
showClearButton={true}
|
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>
|
</div>
|
||||||
|
|
||||||
<!-- <hr class="border-gray-100 dark:border-gray-850 my-1" /> -->
|
<!-- <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}
|
||||||
{#if chatList.length === 0}
|
{#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')}
|
{$i18n.t('No results found')}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/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)}
|
{#if idx === 0 || (idx > 0 && chat.time_range !== chatList[idx - 1].time_range)}
|
||||||
<div
|
<div
|
||||||
class="w-full text-xs text-gray-500 dark:text-gray-500 font-medium {idx === 0
|
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)}
|
{$i18n.t(chat.time_range)}
|
||||||
<!-- localisation keys for time_range to be recognized from the i18next parser (so they don't get automatically removed):
|
<!-- localisation keys for time_range to be recognized from the i18next parser (so they don't get automatically removed):
|
||||||
@ -132,9 +156,16 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<a
|
<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}"
|
href="/c/{chat.id}"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
|
data-arrow-selected={selectedIdx === idx ? 'true' : undefined}
|
||||||
|
on:mouseenter={() => {
|
||||||
|
selectedIdx = idx;
|
||||||
|
}}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
show = false;
|
show = false;
|
||||||
onClose();
|
onClose();
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
export let placeholder = '';
|
export let placeholder = '';
|
||||||
export let value = '';
|
export let value = '';
|
||||||
export let showClearButton = false;
|
export let showClearButton = false;
|
||||||
|
export let onKeydown = (e) => {};
|
||||||
|
|
||||||
let selectedIdx = 0;
|
let selectedIdx = 0;
|
||||||
|
|
||||||
@ -145,6 +146,10 @@
|
|||||||
// if the user types something, reset to the top selection.
|
// if the user types something, reset to the top selection.
|
||||||
selectedIdx = 0;
|
selectedIdx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!document.getElementById('search-options-container')) {
|
||||||
|
onKeydown(e);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -164,6 +169,7 @@
|
|||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<div
|
<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"
|
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 }}
|
in:fade={{ duration: 50 }}
|
||||||
on:mouseenter={() => {
|
on:mouseenter={() => {
|
||||||
selectedIdx = null;
|
selectedIdx = null;
|
||||||
|
Loading…
Reference in New Issue
Block a user