feat(SearchBar): create SearchBar component with input and popover that contains search results

This commit is contained in:
Ilia Mashkov
2026-01-09 16:19:22 +03:00
parent c863bea2dc
commit 9598d8c3e4

View File

@@ -0,0 +1,82 @@
<script lang="ts">
import { Input } from '$shared/shadcn/ui/input';
import { Label } from '$shared/shadcn/ui/label';
import {
Content as PopoverContent,
Root as PopoverRoot,
Trigger as PopoverTrigger,
} from '$shared/shadcn/ui/popover';
import { useId } from 'bits-ui';
import {
type Snippet,
tick,
} from 'svelte';
interface Props {
id: string;
value: string;
class?: string;
placeholder?: string;
label?: string;
children: Snippet<[{ id: string }]> | undefined;
}
let {
id = 'search-bar',
value = $bindable(),
class: className,
placeholder,
label,
children,
}: Props = $props();
let open = $state(false);
let triggerRef = $state<HTMLInputElement>();
const contentId = useId(id);
function closeAndFocusTrigger() {
open = false;
tick().then(() => {
triggerRef?.focus();
});
}
function handleKeyDown(event: KeyboardEvent) {
if (event.key === 'ArrowDown' || event.key === 'ArrowUp' || event.key === 'Enter') {
event.preventDefault();
}
}
function handleInputClick() {
open = true;
tick().then(() => {
triggerRef?.focus();
});
}
</script>
<PopoverRoot>
<PopoverTrigger bind:ref={triggerRef}>
{#snippet child({ props })}
<div {...props} class="flex flex-row flex-1 w-full">
{#if label}
<Label for={id}>{label}</Label>
{/if}
<Input
id={id}
placeholder={placeholder}
bind:value={value}
onkeydown={handleKeyDown}
class="flex flex-row flex-1"
/>
</div>
{/snippet}
</PopoverTrigger>
<PopoverContent
onOpenAutoFocus={e => e.preventDefault()}
class="w-max"
>
{@render children?.({ id: contentId })}
</PopoverContent>
</PopoverRoot>