Gå til innholdet

Popover

Panelet bruker nettleserens egen popover, så det havner i topplaget og legger seg over alt annet uten at noen trenger å finne en z-index som er høy nok.

Resten gjør komponenten. Panelet åpnes i manual-modus, ikke auto, siden nettleserens egen lukking rekker å lukke panelet før knappen får klikket sitt, og knappen da ikke kan brukes til å lukke igjen. Escape, klikk utenfor og fokus tilbake til knappen er derfor skrevet i komponenten. Skriver du popover uten verdi for hånd, er panelet auto, og da følger komponenten med når nettleseren lukker det.

Plasseringen er også vår. position-anchor finnes ennå ikke i alle nettlesere, så komponenten regner ut posisjonen mot knappen og setter den som to variabler på panelet.

// main.ts, kjøres én gang når appen starter
import { defineFsPopover } from "@fristil/designsystem/popover"
import "@fristil/designsystem/tokens.css"
import "@fristil/designsystem/popover.css"
defineFsPopover()
const boks = fs.popover({ id: "handlinger" })
<fs-popover placement="bottom-end">
<button class="fs-button" data-variant="secondary"
aria-expanded="false" aria-controls="handlinger">Handlinger</button>
<ul class="fs-popover" id="handlinger" popover="manual">
<li><button class="fs-button" data-variant="ghost" type="button">Arkiver saken</button></li>
<li><button class="fs-button" data-variant="ghost" type="button">Last ned som PDF</button></li>
</ul>
</fs-popover>

Komponenten kjenner igjen panelet på popover eller klassen fs-popover, og knappen på aria-controls som peker på panelet, ellers på at den er den første knappen utenfor panelet som ikke peker på noe annet med aria-controls.

Lages markupen med JavaScript, skriver fs.popover() koblingen, id-en, klassen og popover. Kommer den fra en mal uten JavaScript, setter komponenten popover="manual", id-en og aria-controls, og lar det serveren har skrevet stå. Komponenten setter dessuten open på verten, aria-expanded på knappen og posisjonen på panelet. Alt den har skrevet setter den tilbake når en oppdatering fra serveren river det bort. Malen din trenger ingenting ekstra.

Reparasjonen gjelder én vei: har noen bedt om at vinduet er åpent, blir det stående. Sender serveren open, åpnes det, for det er noe serveren faktisk sa.

Lukk med egenskapen, altså meny.open = false, hide() eller toggle(). Det er en beskjed komponenten kan se. Fjerner du attributtet utenfra i stedet, som med Datastars data-attr:open, er det ikke til å skille fra en oppdatering som river det bort, og da setter komponenten det tilbake. Der er server-controlled svaret. Se Markup og oppførsel.

AttributtTypeEffekt
openboolskOm panelet er åpent. Speiles når brukeren åpner og lukker.
placementstrengbottom-start, bottom-end, top-start eller top-end. start og end følger leseretningen, så i en side med dir="rtl" er start høyre kant. Er det ikke plass langs kanten, skyves panelet inn i vinduet framfor å bytte andre. fs.popover({ id, placement }) skriver det på verten, fs.popover.isPlacement sjekker en verdi, og popoverPlacements fra hovedinngangen lister dem
server-controlledboolskServeren eier tilstanden. Komponenten setter ikke open tilbake etter en oppdatering.
NavnHva det er
popover-toggleHendelse med { open: boolean } i detail
show(), hide(), toggle()Metoder på elementet
const meny = document.querySelector("fs-popover")
meny.addEventListener("popover-toggle", (hendelse) => {
console.log(hendelse.detail.open ? "åpnet" : "lukket")
})

Panelet flytter seg med siden når brukeren ruller eller endrer vindusstørrelsen. Er det ikke plass under knappen, legger det seg over.

Komponenten rendrer i vanlig DOM, så markupen din treffes av vanlige selektorer:

KlasseHva det er
.fs-popoverPanelet. Komponenten kjenner det igjen på klassen eller på popover, og fyller inn den andre
VariabelStandard
--fs-popover-widthmin(20rem, calc(100vw - var(--fs-spacing-8)))
--fs-popover-paddingvar(--fs-spacing-3)
--fs-popover-radiusvar(--fs-spacing-1)
--fs-popover-topsettes av komponenten
--fs-popover-leftsettes av komponenten

Posisjonen settes som --fs-popover-top og --fs-popover-left på elementet. De to er regnet ut fra knappens plass på skjermen, og er de eneste verdiene komponenten skriver inn direkte. Alt annet står i stilarket, så du kan overstyre det uten !important.

Se Tilpasning for hvordan variablene og laget virker.

  • Panelet er ikke en dialog. Fokus flyttes ikke inn automatisk, og resten av siden er fortsatt i bruk. Trenger du å stoppe brukeren, bruk Dialog.
  • Escape lukker og gir fokus tilbake til knappen. Uten det står fokus på noe som ikke finnes lenger.
  • Innholdet i panelet skal kunne nås med Tab, i samme rekkefølge som det står i markupen.
  • Ikke legg et skjema som må fylles ut i et panel som lukker seg ved klikk utenfor.