SearchCombobox
Hakukenttä
Ehdottaa kirjoittaessa; kuori ilman datakerrosta.
Käyttöpaikat
Suoraan: palvelu tuo osan itse. Välillisesti: osa tulee mukaan toisen paketin osan kautta, ja sen muutos näkyy palvelussa silti. Laskettu julkaisun yhteydessä 23.10.2026.
Käyttö
Paketin README:n luku sellaisenaan.
SearchCombobox — haku ehdottaa kirjoittaessa
<SearchCombobox
search={async (q, signal) => {
const res = await fetch(`/api/haku?q=${encodeURIComponent(q)}`, { signal });
return osumat(await res.json()); // litteä lista ryhmäjärjestyksessä
}}
hitKey={(o) => o.href}
group={(o) => o.ryhma}
renderHit={(o) => (
<>
<ToimittajaIkoni … />
<div className="min-w-0 flex-1">
<div className="truncate">{o.otsikko}</div>
<div className="truncate text-xs text-muted-foreground">{o.selite}</div>
</div>
</>
)}
onOpen={(o) => router.push(o.href)}
onDefault={(q) => router.push(`/tuotteet?haku=${encodeURIComponent(q)}`)}
footer={({ query, close }) => (
<Link href={…} onClick={close} className="block border-t px-3 py-2 text-sm text-muted-foreground">
Kaikki tuotteet haulla "{query}" ↵
</Link>
)}
placeholder="Hae toimittajia, käsittelyjä tai tuotteita"
/>Kuori omistaa ajastuksen ja vanhentuneen vastauksen hylkäyksen, kuluttaja omistaa datan. search kutsutaan vasta kun syöte on vähintään minChars (2) merkkiä ja pysynyt paikallaan delayMs (200 ms); vastaus jonka järjestysnumero ei ole uusin hylätään, ja edellinen pyyntö keskeytetään signalilla. Nuolet valitsevat (nextSelection, viety myös @karkkainen/ui/lib/searchista), Enter avaa valitun tai kutsuu onDefaultia, Esc ja klikkaus ulkopuolelle sulkevat.
> Valinta rivillä on `onMouseDown`, ei `onClick`. Kentän blur ehtii > muuten sulkea listan ennen klikkausta. Ja valtuutus on hakureitin > asia, ei kuoren: jos osumien näkyvyys riippuu käyttäjästä, suodata > ryhmä kerrallaan reitissä ja palauta kyvytön ryhmä tyhjänä, ei 403:lla.
Ikonilinjaus riveillä (TP-Perustus 13.10.2026): tunnistava ikoni — esim. toimittajan lyhenne ja väri — vain kun rivin kohde on se entiteetti; muilla riveillä lajin kuvake samassa 32 px paikassa, muuten ikoni ei tunnista mitään. Raskaat lisätiedot (kuvat) haetaan onResultsin jälkeen omalla viiveellään, ei haun vastauksessa.
Puhelimella kuori kääritään Sheetiin (side="top"); se ei ole osa komponenttia.
Tuonti ja lähde
import { SearchCombobox, SearchComboboxPanel } from "@karkkainen/ui";src/components/search-combobox.tsx