Accordion

Release dato: 25.04.2024

Sist oppdatert: 26.05.2025

Accordion (også kalt expandable, trekkspill eller uttrekkspanel) brukes til å gruppere innhold som kan åpnes og lukkes. Det hjelper brukeren å få oversikt og gjør det enklere å fokusere på én ting om gangen. Accordion egner seg godt når du har mye informasjon, men ikke ønsker å overvelde brukeren.

Har du noen innspill til komponenten?Gi oss beskjed!

Test komponenten

Hvordan kan jeg kontakte Punkt?
Vi er tilgjengelige i #punkt på Oslo kommunes Slack. Ellers er vi veldig åpne for PRer, tilbakemeldinger og innspill!
Når er neste MøtePunkt?
Vi har MøtePunkt 4 ganger i året, vanligvis i mars, juni, august og oktober.
Hva er formålet med Punkt?
Punkt er et designsystem for digitale produkter i Oslo kommune. Vi jobber med å skape en enhetlig og intuitiv brukeropplevelse for alle brukere i kommunen.

Kodebygger

PktAccordion

Utseende
Hvordan accordionen skal se ut
Tilgjengelighet
ID'en til elementet som beskriver accordionen. Brukes for tilgjengelighet.
Innstillinger
Navn på accordion-gruppen, som brukes for å gruppere flere accordion-items sammen.

Innhold

kontakt (PktAccordionItem)

PktAccordionItem

Innhold
Tittelen som vises i sammendraget av elementet. React kan også ta ReactNode (f.eks. ikon + tekst).
Utseende
Overstyrer accordion-forelderens skin når satt. Ellers arves verdi fra pkt-accordion.
Teknisk
ID-en til accordion-elementet
Navn på accordion-element, som brukes for å gruppere flere accordion-elementer sammen. Arves fra foreldre-accordion når utelatt.
React: kalles ved klikk på <details>. Brukes bl.a. for manuell styring av isOpen når kun én rad skal være åpen om gangen. Elements har ingen tilsvarende prop.
React: kalles når <details> toggles. Elements har ingen tilsvarende prop.
motepunkt (PktAccordionItem)

PktAccordionItem

Innhold
Tittelen som vises i sammendraget av elementet. React kan også ta ReactNode (f.eks. ikon + tekst).
Utseende
Overstyrer accordion-forelderens skin når satt. Ellers arves verdi fra pkt-accordion.
Teknisk
ID-en til accordion-elementet
Navn på accordion-element, som brukes for å gruppere flere accordion-elementer sammen. Arves fra foreldre-accordion når utelatt.
React: kalles ved klikk på <details>. Brukes bl.a. for manuell styring av isOpen når kun én rad skal være åpen om gangen. Elements har ingen tilsvarende prop.
React: kalles når <details> toggles. Elements har ingen tilsvarende prop.
formal (PktAccordionItem)

PktAccordionItem

Innhold
Tittelen som vises i sammendraget av elementet. React kan også ta ReactNode (f.eks. ikon + tekst).
Utseende
Overstyrer accordion-forelderens skin når satt. Ellers arves verdi fra pkt-accordion.
Teknisk
ID-en til accordion-elementet
Navn på accordion-element, som brukes for å gruppere flere accordion-elementer sammen. Arves fra foreldre-accordion når utelatt.
React: kalles ved klikk på <details>. Brukes bl.a. for manuell styring av isOpen når kun én rad skal være åpen om gangen. Elements har ingen tilsvarende prop.
React: kalles når <details> toggles. Elements har ingen tilsvarende prop.

Relaterte komponenter

Varianter

Typer

Accordion har to ulike typer med ulike bruksområder:

TypeBeskrivelse
StandardFlere rader kan åpnes samtidig
Single (en åpen)Brukes når bare ett panel bør være åpent, for eksempel ved trinnvis guiding eller steg-for-steg-informasjon
Eksempel på standard accordion med flere åpne rader.Eksempel på single accordion med én åpen rad.

Størrelser

Accordion kommer i to ulike størrelser:

StørrelseBeskrivelse
DefaultStandard størrelse. Brukes når du har vanlig mengde innhold og vil at komponenten skal ta litt mer plass for bedre lesbarhet.
CompactKompakt størrelse. Brukes når du vil spare plass eller når accordion skal stå i et område med mange andre elementer. Passer godt der du vil ha en mer kompakt og diskret løsning.
Eksempel på default accordion med standard størrelse.Eksempel på compact accordion med kompakt størrelse.

Skins

Accordion kommer i fem ulike skins (farger og styling):

SkinBeskrivelse
BorderlessEnkel bakgrunnsfarge og stil
BorderKantlinje på radene
GrayAnnenhver rad er grå
BeigeAnnenhver rad er beige
BlueAnnenhver rad er blå

Borderless, Border og Gray støtter mørk modus. Beige og blue har ingen mørk variant. Der beholdes alle radene fargene fra lys modus, også de hvite radene og teksten.

Eksempel på borderless accordion.Eksempel på blue accordion.Eksempel på accordion med border.

Retningslinjer for bruk

Bruk accordion når

  • du vil presentere mye informasjon uten å overvelde brukeren
  • brukeren ikke trenger å lese alt for å forstå helheten
  • du har relaterte temaer som kan grupperes sammen

Unngå accordion når

  • alt innhold må leses i én sammenheng for å forstå helheten
  • du trenger mer kompleks interaktivitet, bruk heller modal eller tabs

Radene må ha tydelige overskrifter

Tittelen i hvert rad må være beskrivende og kort. Brukeren må forstå hva de finner bak hver rad uten å måtte åpne den. De bør også kun inneholde ett enkelt tema.

Gjør slik

Skriv tydelige og beskrivende overskrifter

Unngå

Unngå lange og ulogiske titler med flere temaer

Hold innholdet kort og konsist

Innholdet i hver rad bør være maks én til to korte setninger. Hvis det blir for langt, vurder å dele opp innholdet eller flytte det til en egen side.

Gjør slik

Skriv tydelig og så kort som mulig i radene

Unngå

Unngå å bruke accordion til veldig langt innhold, led heller brukeren til en annen side om du har mye innhold

Bruk accordion til innhold som logisk hører sammen

Accordion skal hjelpe brukeren å orientere seg. Derfor må innholdet høre sammen. Tenk på det som en liste med elementer som tilhører samme kategori.

Gjør slik

Accordion med relatert innhold
Hold innholdet i accordion relatert til hverandre

Unngå

Eksempel på accordion med urelatert innhold
Unngå å bruke accordion til å samle informasjon som ikke hører sammen

Responsivitet

Accordion fungerer godt på alle skjermstørrelser. Den kollapser eller ekspanderer innhold uten å endre layout.

Du bør likevel teste og forsikre deg om at

  • overskrifter ikke avkortes
  • det er lett å se hva som er åpent/lukket, også på mobil
  • marginer og spacing mellom radene er riktig
Accordion på mobil

Universell utforming

Innholdet må gi mening med skjermleser

Accordion må være tilgjengelig for alle, også for brukere som navigerer med tastatur eller bruker skjermleser. Bruker du komponenten som den er vil du få funksjonaliteten, men du burde forsikre deg om at innholdet gjør det lett for brukeren å navigere i komponenten.

Komponenten støtter

  • navigasjon mellom accordion-rader med “Tab” og “Shift” + “Tab”
  • åpning og lukking av rader med Enter eller Space
  • tydelig visuell fokusindikator når en rad er i fokus
  • tydelig markering av hvilken rad som er åpen

Er Punkt sin accordion tilgjengelig nok?

Punkt sin accordion-komponent bruker HTML-elementene details og summary. Dette er fordi disse elementene er semantiske og tilgjengelige i seg selv. Når man først leser om accordion på internett refereres det ofte til en test gjort av Haskall i 2019 som argumentasjon for å bruke andre alternativer (ofte buttons wrappet i headings som f.eks. WAI-ARIA sin accordion Pattern. Dette er fordi details og summary-elementene har hatt dårlig støtte i enkelte skjermlesere tidligere. Dette er noe som har blitt, og blir bedre med tiden. I dag er støtten god nok til at vi kan bruke disse elementene.

Mer om universell utforming av accordion:

Anatomi

ElementBeskrivelse
1. Tittel (valgfritt)Brukes som en forklaring over hele accordion-gruppen
2. Åpne- og lukke-ikonViser status og gir visuell ledetråd (pil-ikon)
3. OverskriftTittel på hver rad, vises som summary
4. InnholdTeksten eller innholdet som vises når raden åpnes
Accordion anatomi hvor de fire elementene er markert.

Implementasjon i kode

Accordion lar brukeren åpne og lukke innhold. I Punkt er komponenten bygget på de semantiske HTML-elementene <details> og <summary>. Dette gir innebygd støtte for tastaturnavigasjon og gjør komponenten både enkel og tilgjengelig.

For React og Elements tilbyr Punkt både wrapper-komponenten <PktAccordion> og enkeltstående <PktAccordionItem>.

Som standard kan flere accordion-rader være åpne samtidig. Ønsker du at kun én rad skal være åpen, må du styre tilstanden selv. Les mer under “Begrens antall åpne rader”.

Hvordan ta komponenten i bruk?

import @oslokommune/punkt-elements/dist/pkt-accordion.js;
import @oslokommune/punkt-elements/dist/pkt-accordion-item.js;
import { PktAccordion, PktAccordionItem } from '@oslokommune/punkt-react';
<script src="https://punkt-cdn.oslo.kommune.no/19/elements/pkt-accordion.js" type="module"></script>
<script src="https://punkt-cdn.oslo.kommune.no/19/elements/pkt-accordion-item.js" type="module"></script>

Testing

Elements: Dersom du skal skrive tester med JSDOM eller liknende er det viktig at du lar komponenten bli rendret ferdig før du tester den. Dette kan gjøres ved å kjøre denne kodelinjen før testene kjøres:

await window.customElements.whenDefined("pkt-accordion");

Begrens antall åpne rader

Som standard støtter Accordion åpning av flere rader samtidig. For å styre at kun én rad kan være åpen om gangen, må man styre alle radene sin toggle tilstand lokalt - det vil si at man må overstyre den automatiske tilstandshåndteringen til komponenten. Dette gjøres ved å sette en boolean isOpen og en onClick/click funksjon på <AccordionItem>/<pkt-accordion-item> som styrer åpne-lukke tilstanden til komponenten.

I React trenger man å sende inn event for å forhindre inkonsekvent oppførsel. Dette er fordi <details>-elementet har sin egen innebygde toggle-funksjon som kan føre til inkonsekvens når vi prøver å sette isOpen-propen i React. I <AccordionItem> kjører vi e.preventDefault() for å forhindre at <details>-elementet sin innebygde toggle-funksjon kjører. Sjekk eksemplene under!

<script>
  @state() private openedItem: string = ''
  function toggleCurrentOpenItem(e: MouseEvent, id: string) {
    e.preventDefault() // Prevent default behavior to ensure controlled state
    if (this.openedItem === id) {
      this.openedItem = ''
    } else {
      this.openedItem = id
    }
  }
</script>

<pkt-accordion skin="blue" aria-labelledby="accordion-standard">
  <pkt-accordion-item
    id=${item.id}
    title=${item.title}
    .isOpen=${this.openedItem == item.id}
    @click=${(e: MouseEvent) => this.toggleCurrentOpenItem(e, item.id)}
  >
    ${item.content}
    <p>Element innhold</p>
  </pkt-accordion-item>
</pkt-accordion>
const [openedItem, setOpenedItem] = useState<string>('')

const toggleCurrentOpenItem = (e: React.MouseEvent, id: string) => {
  if (openedItem.includes(id)) {
    setOpenedItem('')
  } else {
    setOpenedItem(id)
  }
}

return (
  <PktAccordion compact skin={"borderless"}>
    {accordionItems.map((item, index) => {
      return (
        <PktAccordionItem
          id={item.id}
          key={item.id}
          title={item.title}
          defaultOpen={index === 0}
          isOpen={openedItem === item.id}
          onClick={(e) => toggleCurrentOpenItem(e, item.id)}
        >
          {item.content}
        </PktAccordionItem>
      );
    })}
  </PktAccordion>
)

Egenskaper

PktAccordion

Props

Prop:
skin?
Type:
"borderless" | "outlined" | "gray" | "beige" | "blue" | "plus-minus"
Standardverdi:
"borderless"
Beskrivelse:
Hvordan accordionen skal se ut
Prop:
ariaLabelledBy?
aria-labelledby?
Type:
string
Beskrivelse:
ID'en til elementet som beskriver accordionen. Brukes for tilgjengelighet.
Prop:
compact?
Type:
boolean
Standardverdi:
false
Beskrivelse:
En kompakt accordion har mindre padding og margin
Prop:
name?
Type:
string
Beskrivelse:
Navn på accordion-gruppen, som brukes for å gruppere flere accordion-items sammen.

Slots

Slot:
default
Beskrivelse:
Accordion-elementene som skal vises i accordionen

PktAccordionItem

Props

Prop:
title?
Type:
string
Beskrivelse:
Tittelen som vises i sammendraget av elementet. React kan også ta ReactNode (f.eks. ikon + tekst).
Prop:
id
Type:
string
Beskrivelse:
ID-en til accordion-elementet
Prop:
defaultOpen?
Type:
boolean
Standardverdi:
false
Beskrivelse:
Et accordion-element kan settes til å være åpent som standard når siden lastes
Prop:
isOpen?
Type:
boolean
Beskrivelse:
En prop som kan brukes til å overstyre lokal isOpen-tilstand, og beskriver om accordion-elementet er åpent eller ikke
Prop:
name?
Type:
string
Beskrivelse:
Navn på accordion-element, som brukes for å gruppere flere accordion-elementer sammen. Arves fra foreldre-accordion når utelatt.
Prop:
skin?
Type:
"borderless" | "outlined" | "gray" | "beige" | "blue" | "plus-minus"
Beskrivelse:
Overstyrer accordion-forelderens skin når satt. Ellers arves verdi fra pkt-accordion.
Prop:
compact?
Type:
boolean
Beskrivelse:
Overstyrer accordion-forelderens compact når satt. Ellers arves verdi fra pkt-accordion.
Prop:
onClick?
Type:
(event: MouseEvent) => void
Beskrivelse:
React: kalles ved klikk på <details>. Brukes bl.a. for manuell styring av isOpen når kun én rad skal være åpen om gangen. Elements har ingen tilsvarende prop.
Prop:
onToggle?
Type:
(event: SyntheticEvent) => void
Beskrivelse:
React: kalles når <details> toggles. Elements har ingen tilsvarende prop.

Slots

Slot:
default
Beskrivelse:
Innholdet i accordion-elementet