Route search triggers to the inline input via the DOM
This commit is contained in:
parent
a5237a5e75
commit
fecfbaab8b
2 changed files with 10 additions and 20 deletions
|
|
@ -2,17 +2,11 @@
|
||||||
import { goto } from "$app/navigation";
|
import { goto } from "$app/navigation";
|
||||||
import type { SearchResult } from "$lib/search";
|
import type { SearchResult } from "$lib/search";
|
||||||
import { createSearchState } from "$lib/searchState.svelte";
|
import { createSearchState } from "$lib/searchState.svelte";
|
||||||
import { registerInlineSearch } from "$lib/searchModal.svelte";
|
|
||||||
import SearchResults from "$lib/components/SearchResults.svelte";
|
import SearchResults from "$lib/components/SearchResults.svelte";
|
||||||
|
|
||||||
const search = createSearchState();
|
const search = createSearchState();
|
||||||
|
|
||||||
let open = $state(false);
|
let open = $state(false);
|
||||||
let inputEl = $state<HTMLInputElement | null>(null);
|
|
||||||
|
|
||||||
// Route the global "/" shortcut and the sidebar/menu triggers here while
|
|
||||||
// this input is on screen
|
|
||||||
$effect(() => registerInlineSearch(() => inputEl?.focus()));
|
|
||||||
|
|
||||||
function onInput() {
|
function onInput() {
|
||||||
search.schedule();
|
search.schedule();
|
||||||
|
|
@ -61,8 +55,8 @@
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<input
|
<input
|
||||||
bind:this={inputEl}
|
|
||||||
bind:value={search.query}
|
bind:value={search.query}
|
||||||
|
data-search-inline
|
||||||
type="search"
|
type="search"
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
role="combobox"
|
role="combobox"
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,21 @@
|
||||||
let open = $state(false);
|
let open = $state(false);
|
||||||
|
|
||||||
// When a page hosts an inline search input (the homepage), it registers a
|
|
||||||
// focus function here and every search trigger routes to it instead of the
|
|
||||||
// modal, so a modal input never opens on top of an inline one.
|
|
||||||
let inlineFocus: (() => void) | null = null;
|
|
||||||
|
|
||||||
export const searchModal = {
|
export const searchModal = {
|
||||||
get open() {
|
get open() {
|
||||||
return open;
|
return open;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function registerInlineSearch(focus: () => void): () => void {
|
// When the page hosts an inline search input (the homepage), every search
|
||||||
inlineFocus = focus;
|
// trigger focuses it instead of opening the modal, so a modal input never
|
||||||
return () => {
|
// opens on top of an inline one. Resolved through the DOM rather than a
|
||||||
if (inlineFocus === focus) inlineFocus = null;
|
// registration callback: it needs no lifecycle bookkeeping and stays correct
|
||||||
};
|
// even if HMR instantiates this module twice in dev.
|
||||||
}
|
|
||||||
|
|
||||||
export function openSearch() {
|
export function openSearch() {
|
||||||
if (inlineFocus) inlineFocus();
|
const inline = document.querySelector<HTMLInputElement>(
|
||||||
|
"[data-search-inline]",
|
||||||
|
);
|
||||||
|
if (inline) inline.focus();
|
||||||
else open = true;
|
else open = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue