spb/satelliteindex
Public
TypeScript 66.5%
Python 30.9%
JavaScript 1.4%
CSS 0.7%
1'use client';2import { Search, X } from 'lucide-react';3import { useRouter, useSearchParams } from 'next/navigation';4import { useState } from 'react';5import { routes } from '@/lib/site';67/** Compact search that navigates to `?q=` while keeping the other filters. Degrades to a plain GET form without JS. */8export function SearchBox({ initial = '' }: { initial?: string }) {9 const router = useRouter();10 const sp = useSearchParams();11 const [value, setValue] = useState(initial);1213 const go = (q: string) => {14 const p = new URLSearchParams(sp.toString());15 p.delete('page');16 if (q.trim()) p.set('q', q.trim());17 else p.delete('q');18 const s = p.toString();19 router.push(routes.satellites(s || undefined));20 };2122 return (23 <form24 method="get"25 action={routes.satellites()}26 role="search"27 className="relative flex w-full max-w-md items-center"28 onSubmit={(e) => {29 e.preventDefault();30 go(value);31 }}32 >33 {Array.from(sp.entries()).filter(([k]) => k !== 'q' && k !== 'page').map(([k, v]) => <input key={k} type="hidden" name={k} value={v} />)}34 <Search className="pointer-events-none absolute left-3 size-4 text-ink-3" aria-hidden />35 <input36 type="search"37 name="q"38 value={value}39 onChange={(e) => setValue(e.target.value)}40 placeholder="Name, NORAD or COSPAR id…"41 aria-label="Search satellites by name, NORAD or COSPAR id"42 className="h-11 w-full rounded-md border border-rule bg-plane-2 pl-9 pr-10 text-sm text-ink placeholder:text-ink-3 focus:border-accent/60"43 autoComplete="off"44 />45 {value && (46 <button47 type="button"48 onClick={() => {49 setValue('');50 go('');51 }}52 className="absolute right-1 inline-flex size-9 items-center justify-center rounded text-ink-3 hover:text-ink"53 aria-label="Clear search"54 >55 <X className="size-4" aria-hidden />56 </button>57 )}58 </form>59 );60}61