Hopp til hovedinnhold
Meny

lmfaole.party / designsystem / komponenter / Søk med filtrering

  • Forside
  • Turer
  • Økonomi
  • Slides
  • <lm-sok> – Søk med filtrering / Faceted search

    Om komponenten

    Formål

    Gir en fullverdig søkeside over et hvilket som helst flatt JSON-datasett: fritekstsøk, avkrysningsbaserte type-/kategori-filtre, et ARIA-mønster-filter og fire sorteringsvalg (relevans, navn, sist endret, mest brukt). Bygger selv de riktige avkrysningsboksene (med treff-antall) fra det faktiske datasettet - ingen fasetter må konfigureres manuelt.

    Merk: Brukes i dag av designsystemets egen /designsystem/sok/index.html-side (over sok-indeks.json), men vet ingenting om designsystemet spesifikt - kilde/data kan peke på et hvilket som helst datasett med samme feltnavn.

    Egner seg for

    • En dedikert søkeside som skal la brukeren finne fram i et større, kategorisert katalog (komponenter, artikler, produkter, dokumentasjon).
    • Datasett som allerede finnes som en flat, statisk generert JSON-fil - ingen server-søk eller paginering trengs.

    Egner seg ikke for

    • Et lite, raskt "hopp til side"-hurtigsøk i en sidebar - se den enklere, håndskrevne implementasjonen i designsystem.js/.designsystem-sok for det behovet.
    • Datasett med tusenvis av rader der server-side søk/paginering er nødvendig av ytelsesgrunner - komponenten laster og filtrerer hele datasettet i nettleseren.

    Bruk

    Enkleste bruk peker kilde på en ferdig generert JSON-indeks:

    <script type="module" src="/designsystem/komponenter/navigasjon/sok/sok.js"></script>
    
    <lm-sok kilde="/designsystem/sok-indeks.json" synk-url></lm-sok>

    Sette data direkte (hopper over henting via kilde)

    const sok = document.querySelector("lm-sok");
    sok.data = await fetch("/mitt-eget-datasett.json").then((r) => r.json());
    
    sok.addEventListener("sok:oppdatert", (e) => {
        document.title = `Søk (${e.detail.antall} treff) - Mitt nettsted`;
    });

    Prøv selv

    Rediger koden under - resultatet oppdateres live.

    Attributter

    Attributt Type Standard Beskrivelse
    kildestring (URL)nullAttributt/property. URL til søkeindeksen (JSON-array av {navn, type, kategori, synonymer, beskrivelse, lenke, sistEndret, brukesAvAntall, harAriaMonster}). Hentes automatisk når attributtet settes/endres.
    synk-urlbooleanfalseAttributt. Når til stede, synkroniseres søkeord/filtre/sortering med URL-ens spørrestreng (?q=...&type=...&kategori=...&sortering=...&aria=1) via history.replaceState, slik at et søk kan lenkes/deles og fungerer med nettleserens fram/tilbake.
    plassholderstring"Søk (f.eks. «modal», «avstand», «tabell»)"Attributt. Overstyrer plassholderteksten i søkefeltet.
    dataArray<object>[]Property. Elementene som søkes/filtreres i - kan settes direkte for å hoppe over henting via kilde (f.eks. når data allerede er hentet av forbrukeren).

    Events

    Event Type Beskrivelse
    sok:oppdatertCustomEvent<{antall: number, totalt: number}>Sendes hver gang det synlige resultatsettet endres (nytt søkeord, filter eller sortering) - detail.antall er antall synlige treff, detail.totalt er hele datasettets størrelse.

    Parts

    Part Beskrivelse
    verktoylinjeDen øverste raden med søkefelt, filtre og sortering.
    feltSelve søkefeltet (<input type="search">).
    type-filter<fieldset>-en med type-avkrysningsboksene (Komponent/Funksjon/Token).
    kategori-filter<fieldset>-en med kategori-avkrysningsboksene.
    kategori-listeDen skrollbare listen av kategori-avkrysningsbokser inni kategori-filter.
    sortering<select>-en for sorteringsvalg.
    nullstill«Nullstill filter»-knappen (skjult når ingen filter er aktive).
    antall-treffDen «X av Y treff»-teksten (role="status", kunngjøres av skjermlesere).
    resultater<ul>-en med treffene.
    resultatHvert enkelt treff (<li>) i resultatlisten.

    Styling med ::part()

    Hver part over kan restyles direkte fra et vanlig, ytre stilark - uten å måtte endre selve komponenten eller duplisere den:

    lm-sok::part(verktoylinje) {
        /* egne stiler for "Den øverste raden med søkefelt, filtre og sortering." */
    }
    
    lm-sok::part(felt) {
        /* egne stiler for "Selve søkefeltet (`<input type="search">`)." */
    }
    
    lm-sok::part(type-filter) {
        /* egne stiler for "`<fieldset>`-en med type-avkrysningsboksene (Komponent/Funksjon/Token)." */
    }
    
    lm-sok::part(kategori-filter) {
        /* egne stiler for "`<fieldset>`-en med kategori-avkrysningsboksene." */
    }
    
    lm-sok::part(kategori-liste) {
        /* egne stiler for "Den skrollbare listen av kategori-avkrysningsbokser inni kategori-filter." */
    }
    
    lm-sok::part(sortering) {
        /* egne stiler for "`<select>`-en for sorteringsvalg." */
    }
    
    lm-sok::part(nullstill) {
        /* egne stiler for "«Nullstill filter»-knappen (skjult når ingen filter er aktive)." */
    }
    
    lm-sok::part(antall-treff) {
        /* egne stiler for "Den «X av Y treff»-teksten (`role="status"`, kunngjøres av skjermlesere)." */
    }
    
    lm-sok::part(resultater) {
        /* egne stiler for "`<ul>`-en med treffene." */
    }
    
    lm-sok::part(resultat) {
        /* egne stiler for "Hvert enkelt treff (`<li>`) i resultatlisten." */
    }

    Tilgjengelighet

    Alle filterkontroller er native og tastaturoperable (checkboxer, select). Treff-antallet står i et role="status"-element som kunngjør endringer for skjermlesere uten å flytte fokus. Fasett-avkrysningsboksene bygges kun én gang per datasett (ikke ved hvert tastetrykk), slik at fokus/tastaturposisjon aldri mistes når en boks krysses av.

    • Type-/kategori-/ARIA-mønster-filtre er native <input type="checkbox"> i <fieldset>/<legend>-grupper - full tastaturstøtte og skjermleser-gruppering uten egen ARIA.
    • Sorteringsvalget er en native <select>.
    • Treff-antallet (role="status") kunngjøres automatisk av skjermlesere når det endres, uten å stjele fokus fra søkefeltet eller filtrene.
    • Fasett-avkrysningsboksene bygges kun én gang per datasett (#byggFasetter() kalles fra data-setteren, ikke fra søkefeltets input-lytter) - dette er bevisst, for å unngå at et helt nytt sett med DOM-noder (og dermed tapt fokus) opprettes hver gang brukeren krysser av en boks.

    Detaljer

    • Søkefeltet er debouncet (150ms) - filtrering skjer ikke ved hvert eneste tastetrykk under rask skriving.
    • Fasett-tellerne ("Komponent (32)") viser alltid antallet i hele datasettet, ikke et tall som endrer seg etter hvert som andre filtre justeres - et bevisst enkelt valg som unngår kompleks "faceted count"-omregning og den destruktive re-rendringen den ville krevd (se tilgjengelighetDetaljer).
    • synk-url bruker history.replaceState (ikke pushState) - hvert tastetrykk/filtervalg skal ikke skape en egen oppføring i nettleserhistorikken.
    • Relevans-sortering (standard når det søkes) rangerer eksakt navnetreff først, så "navn starter med søket", så resten - alfabetisk innad i hver gruppe.

    Referanser

    Se også:

    Brukes av:

    • designsystem/sok/index.html - designsystemets egen søkeside, over designsystem/sok-indeks.json.

    Avhengigheter: designsystem/komponenter/innhold/tag/tag.js