an atproto based link aggregator
at main 55 lines 1.4 kB view raw
1<script lang="ts"> 2 import { goto } from '$app/navigation'; 3 4 interface Props { 5 compact?: boolean; 6 } 7 8 let { compact = false }: Props = $props(); 9 10 let query = $state(''); 11 let inputEl: HTMLInputElement; 12 13 function handleSubmit(e: Event) { 14 e.preventDefault(); 15 if (query.trim().length >= 2) { 16 goto(`/search?q=${encodeURIComponent(query.trim())}`); 17 query = ''; 18 inputEl?.blur(); 19 } 20 } 21 22 function handleKeydown(e: KeyboardEvent) { 23 // Allow Escape to blur 24 if (e.key === 'Escape') { 25 query = ''; 26 inputEl?.blur(); 27 } 28 } 29</script> 30 31<form onsubmit={handleSubmit} class="relative"> 32 <input 33 bind:this={inputEl} 34 bind:value={query} 35 onkeydown={handleKeydown} 36 type="search" 37 placeholder={compact ? 'Search...' : 'Search posts...'} 38 class="w-full pl-8 pr-3 py-1.5 text-sm rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-violet-500 focus:border-transparent {compact 39 ? 'w-32 focus:w-48 transition-all' 40 : ''}" 41 /> 42 <svg 43 class="absolute left-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400 dark:text-gray-500" 44 fill="none" 45 stroke="currentColor" 46 viewBox="0 0 24 24" 47 > 48 <path 49 stroke-linecap="round" 50 stroke-linejoin="round" 51 stroke-width="2" 52 d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" 53 /> 54 </svg> 55</form>