Fix search focus

This commit is contained in:
WardPearce
2024-04-13 20:11:26 +12:00
parent 9b120a28fd
commit bc42ae8aab
2 changed files with 89 additions and 67 deletions
+48 -35
View File
@@ -1,9 +1,12 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { createEventDispatcher } from 'svelte';
import { _ } from 'svelte-i18n';
import { interfaceSearchSuggestions } from '../store';
import { getSearchSuggestions } from './Api';
const dispatch = createEventDispatcher();
let searchSuggestions = false;
interfaceSearchSuggestions.subscribe((value) => (searchSuggestions = value));
@@ -11,6 +14,8 @@
let suggestionsForSearch: string[] = [];
let selectedSuggestionIndex: number = -1;
let showSearchBox = false;
let debounceTimer: NodeJS.Timeout;
function debouncedSearch(event: any) {
if (!searchSuggestions) return;
@@ -28,6 +33,7 @@
function handleSubmit() {
selectedSuggestionIndex = -1;
goto(`/search/${encodeURIComponent(search)}`);
dispatch('searchSubmitted');
}
function handleKeyDown(event: KeyboardEvent) {
@@ -50,43 +56,50 @@
<form on:submit|preventDefault={handleSubmit}>
<div class="field prefix round fill no-margin search">
<i class="front">search</i>
<input bind:value={search} on:click={() => document.getElementById('search')?.focus()} />
<menu class="min">
<div class="field large prefix suffix no-margin fixed">
<i class="front">arrow_back</i>
<input
placeholder={$_('searchPlaceholder')}
type="text"
id="search"
required
bind:value={search}
on:keydown={handleKeyDown}
on:keyup={(event) => {
if (event.key === 'Enter') {
handleSubmit();
} else {
debouncedSearch(event);
}
}}
/>
<i class="front" on:click={() => (search = '', suggestionsForSearch = [], selectedSuggestionIndex = -1)}>close</i>
</div>
{#if searchSuggestions}
{#each suggestionsForSearch as suggestion, index}
<a
on:click={() => {
search = suggestion;
handleSubmit();
<input bind:value={search} on:click={() => (showSearchBox = true)} />
{#if showSearchBox}
<menu class="min">
<div class="field large prefix suffix no-margin fixed">
<i class="front" on:click={() => dispatch('searchCancelled')}>arrow_back</i>
<input
placeholder={$_('searchPlaceholder')}
type="text"
autofocus={true}
required
bind:value={search}
on:keydown={handleKeyDown}
on:keyup={(event) => {
if (event.key === 'Enter') {
handleSubmit();
} else {
debouncedSearch(event);
}
}}
class="row"
class:selected={index === selectedSuggestionIndex}
href={`/search/${encodeURIComponent(suggestion)}`}
/>
<i
class="front"
on:click={() => (
(search = ''), (suggestionsForSearch = []), (selectedSuggestionIndex = -1)
)}>close</i
>
<div>{suggestion}</div>
</a>
{/each}
{/if}
</menu>
</div>
{#if searchSuggestions}
{#each suggestionsForSearch as suggestion, index}
<a
on:click={() => {
search = suggestion;
handleSubmit();
}}
class="row"
class:selected={index === selectedSuggestionIndex}
href={`/search/${encodeURIComponent(suggestion)}`}
>
<div>{suggestion}</div>
</a>
{/each}
{/if}
</menu>
{/if}
</div>
</form>
+41 -32
View File
@@ -45,6 +45,8 @@
themeColor
} from '../store';
let mobileSearchShow = false;
let currentPage: string | null = '';
activePage.subscribe((page) => (currentPage = page));
@@ -290,6 +292,15 @@
</nav>
<nav class="top">
{#if !mobileSearchShow}
<button
on:click={() => (mobileSearchShow = !mobileSearchShow)}
class="transparent s circle large"
>
<i>search</i>
</button>
{/if}
<button class="circle large transparent m l small-margin" data-ui="#menu-expanded"
><i>menu</i></button
>
@@ -297,47 +308,45 @@
<Logo classes="m l" />
<h6 class="m l">Materialious</h6>
<div class="max"></div>
<div class="max m l"></div>
<div class="m l">
<Search />
</div>
<div class="max"></div>
<a
href="https://github.com/WardPearce/Materialious"
target="_blank"
rel="noopener noreferrer"
class="button circle large transparent"
>
<i>code</i>
<div class="tooltip bottom">{$_('layout.star')}</div>
</a>
<button data-ui="#sync-party" class="circle large transparent">
<i class:primary-text={$syncPartyPeer}>group</i>
<div class="tooltip bottom">{$_('layout.syncParty')}</div>
</button>
{#if isLoggedIn}
<button class="circle large transparent" data-ui="#dialog-notifications"
><i>notifications</i>
<div class="tooltip bottom">{$_('layout.notifications')}</div>
</button>
{#if !mobileSearchShow}
<div class="max"></div>
{/if}
<button class="circle large transparent" data-ui="#dialog-settings">
<i>settings</i>
<div class="tooltip bottom">{$_('layout.settings')}</div>
</button>
{#if !isLoggedIn}
<button on:click={login} class="circle large transparent">
<i>login</i>
<div class="tooltip bottom">{$_('layout.login')}</div>
</button>
{#if mobileSearchShow}
<Search on:searchCancelled={() => (mobileSearchShow = false)} />
{:else}
<button on:click={logout} class="circle large transparent">
<i>logout</i>
<div class="tooltip bottom">{$_('layout.logout')}</div>
<button data-ui="#sync-party" class="m l circle large transparent">
<i class:primary-text={$syncPartyPeer}>group</i>
<div class="tooltip bottom">{$_('layout.syncParty')}</div>
</button>
{#if isLoggedIn}
<button class="circle large transparent" data-ui="#dialog-notifications"
><i>notifications</i>
<div class="tooltip bottom">{$_('layout.notifications')}</div>
</button>
{/if}
<button class="circle large transparent" data-ui="#dialog-settings">
<i>settings</i>
<div class="tooltip bottom">{$_('layout.settings')}</div>
</button>
{#if !isLoggedIn}
<button on:click={login} class="circle large transparent">
<i>login</i>
<div class="tooltip bottom">{$_('layout.login')}</div>
</button>
{:else}
<button on:click={logout} class="circle large transparent">
<i>logout</i>
<div class="tooltip bottom">{$_('layout.logout')}</div>
</button>
{/if}
{/if}
</nav>