Accordion

Om komponenten

Accordion er en komponent som lar brukeren åpne og lukke innhold.

Vi har valgt å bruke de semantiske details og summary-taggene for å lage en accordion. Dette er en enkel og semantisk måte å lage en accordion på da tastaturnavigering skjer sømløst. Det finnes ulike måter å lage en Accordion på, og du kan lese mer om avgjørelsen under universell utforming”-fanen. For å bruke Punkt sin Accordion er det viktig at <Accordion> brukes som en wrapper rundt <AccordionItem>. Som standard, kan man ha flere åpne rader i Punkt sin Accordion samtidig.

Ofte stilte spørsmål

Kan jeg digge Punkt like mye som jeg gjør nå?
Selvfølgelig! Vi digger støtten din!
Hvordan kan jeg kontakte Punkt?
Vi er tilgjengelige via Slack-kanalen, #origo-punkt. Ellers er vi veldig åpne for PRer, tilbakemeldinger og innspill!
Hva er MøtePunkt?
MøtePunkt er et brukerforum for Punkt-brukere.
<h2 id="accordion-heading-1">Borderless</h2>
<div
  data-testid="pkt-accordion"
  class="pkt-accordion pkt-accordion--borderless"
  aria-labelledby="accordion-heading-1"
>
  <details
    aria-controls="pkt-accordion-item-content-1"
    class="pkt-accordion-item"
    id="pkt-accordion-item-header-1"
  >
    <summary
      aria-labelledby="pkt-accordion-item-header-1"
      class="pkt-accordion-item__title"
      id="pkt-accordion-item-summary-1"
    >
      Item summary 1
      <span class="pkt-icon pkt-accordion-item__icon">
        <svg viewBox="0 0 32 32" aria-hidden="true">
          <use href="#chevron-thin-down"></use>
        </svg>
      </span>
    </summary>
    <div
      id="pkt-accordion-item-content-1"
      role="region"
      class="pkt-accordion-item__content"
    >
      Item Content 1
    </div>
  </details>
  <details
    aria-controls="pkt-accordion-item-content-2"
    class="pkt-accordion-item"
    id="pkt-accordion-item-header-2"
  >
    <summary
      aria-labelledby="pkt-accordion-item-header-2"
      class="pkt-accordion-item__title"
      id="pkt-accordion-item-summary-2"
    >
      Item summary 1
      <span class="pkt-icon pkt-accordion-item__icon">
        <svg viewBox="0 0 32 32" aria-hidden="true">
          <use href="#chevron-thin-down"></use>
        </svg>
      </span>
    </summary>
    <div
      id="pkt-accordion-item-content-1"
      role="region"
      class="pkt-accordion-item__content"
    >
      Item Content 1
    </div>
  </details>
</div>
  <template>
    <PktAccordion key="acc"  :compact="false" skin="borderless">
      <PktAccordionItem
        v-for="item in accordionItems"
        :key="item.id"
        :id="item.id"
        :title="item.title"
        :toggleProps="{ isOpen: openedItem === item.id, onToggleClick: toggleCurrentOpenItem }"
      >
        {{ item.content }}
      </PktAccordionItem>
    </PktAccordion>
  </template>
<PktAccordion compact={false} skin="blue">
  {accordionItems.map((item, index) => (
    <PktAccordionItem id={item.id} key={item.id} title={item.title}>
      {item.content}
    </PktAccordionItem>
  ))}
</PktAccordion>

Avhengigheter

Ikoner:

  • chevron-thin-down

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 i Vue eller React. Dette kan gjøres ved å sette toggleProps<AccordionItem>.

Ingen eksempel i ren HTML. Se Vue eller React eksempel
  <template>
       <PktAccordion key="acc"  :compact="false" skin="borderless">
        <PktAccordionItem
          v-for="item in accordionItems"
          :key="item.id"
          :id="item.id"
          :title="item.title"
          :toggleProps="{ isOpen: openedItem === item.id, onToggleClick: toggleCurrentOpenItem }"
        >
          {{ item.content }}
        </PktAccordionItem>
      </PktAccordion>

  </template>
  <script>
      const accordionItems = [
        {
          id: 'apningstid',
          title: 'Hva er åpningstidene?',
          content: 'Accordion item 1 content Accordion item 1 content',
        },
        { id: 'dresscode', title: 'Hva er dressscode for eventet?', content: 'Accordion item 2 content' },
        { id: 'lokale', title: 'Kan jeg ta med mat og drikke til lokalet?', content: 'Accordion item 3 content' },
        { id: 'kjæledyr', title: 'Kan jeg ta med kjæledyr?', content: 'Accordion item  content' },
      ]
  const openedItem = ref<string>('')
  const toggleCurrentOpenItem = (id: string) => {
    // Close the current open item if it's the same as the clicked item
    // Override the value, if it's a new item
    openedItem.value = openedItem.value === id ? '' : id
  }
  </script>
  const [openedItem, setOpenedItem] = useState<string>('')

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

  return (
    <>
      <h3 id="heading-accordion">
      <PktAccordion
        compact={false}
        skin="blue"
      >
        {accordionItems.map((item, index) => (
          <PktAccordionItem id={item.id} key={item.id} title={item.title}>
            {item.content}
          </PktAccordionItem>
        ))}
      </PktAccordion>
      </h3>
    </>
  )

Varianter

Accordion har fire ulike skins:

  • borderless (standard)
  • outlined
  • beige
  • blue

Accordion kommer også i en compact versjon. Som standard, er compactsatt til false.

Kan jeg digge Punkt like mye som jeg gjør nå?
Selvfølgelig! Vi digger støtten din!
Hvordan kan jeg kontakte Punkt?
Vi er tilgjengelige via Slack-kanalen, #origo-punkt. Ellers er vi veldig åpne for PRer, tilbakemeldinger og innspill!
Hva er MøtePunkt?
MøtePunkt er et brukerforum for Punkt-brukere.
Kan jeg digge Punkt like mye som jeg gjør nå?
Selvfølgelig! Vi digger støtten din!
Hvordan kan jeg kontakte Punkt?
Vi er tilgjengelige via Slack-kanalen, #origo-punkt. Ellers er vi veldig åpne for PRer, tilbakemeldinger og innspill!
Hva er MøtePunkt?
MøtePunkt er et brukerforum for Punkt-brukere.
Kan jeg digge Punkt like mye som jeg gjør nå?
Selvfølgelig! Vi digger støtten din!
Hvordan kan jeg kontakte Punkt?
Vi er tilgjengelige via Slack-kanalen, #origo-punkt. Ellers er vi veldig åpne for PRer, tilbakemeldinger og innspill!
Hva er MøtePunkt?
MøtePunkt er et brukerforum for Punkt-brukere.
Kan jeg digge Punkt like mye som jeg gjør nå?
Selvfølgelig! Vi digger støtten din!
Hvordan kan jeg kontakte Punkt?
Vi er tilgjengelige via Slack-kanalen, #origo-punkt. Ellers er vi veldig åpne for PRer, tilbakemeldinger og innspill!
Hva er MøtePunkt?
MøtePunkt er et brukerforum for Punkt-brukere.

CSS oversikt

I Punkt brukes BEM-styling. Under er Accordion sin CSS-struktur.

Block:

  • .pkt-accordion
  • .pkt-accordion-item

Elements:

  • .pkt-accordion-item__title
  • .pkt-accordion-item__icon
  • .pkt-accordion-item__content

Modifiers:

  • .pkt-accordion--borderless
  • .pkt-accordion--outlined
  • .pkt-accordion--beige
  • .pkt-accordion--blue
  • .pkt-accordion-item--open

Props og slots

<Accordion/>

PropsTypeValidationDefaultDescription
classNamestringStyling klasse
childrenReactNode eller ReactNode[]<Accordion> må wrappe rundt <AccordionItem>
compactbooleanfalseMindre padding og tekststørrelse
skinborderless, outlined, beige, blueborderlessHvert skin har en egen bakgrunnsfarge og borderfarge

<AccordionItem/>

PropsTypeValidationDefaultDescription
idstringPåkrevdSettes til en unik id per item for å koble item-header med item-content slik at skjermlesere leser opp innhold korrekt
titlestring PåkrevdEn tittel/oppsummering av innholdet i <AccordionItem>
defaultOpenboolean -falseSett til true dersom man ønsker å la spesifikk <AccordionItem> være åpen når man først laster inn siden
refLegacyRef<HTMLDivElement>-Tillater å hente en ref til komponent instansen.
togglePropsisOpen, onToggleClick()-Sett både isOpen og onToggleClick dersom du ønsker å overskrive den lokale togglingen. F.eks. dersom man ønsker å begrense antall <AccordionItem> som kan være åpne samtidig.
classNamestring-Styling klasse
childrenReactNode eller ReactNode[]-<Accordion> må wrappe rundt <AccordionItem>

toggleProps i Vue og React

Ønsker man å override den lokale togglingen, kan man gjøre det ved å sende inn toggleProps til <AccordionItem>. Da må man sende inn både en boolean isOpen og en onToggleClick funksjon med argumenter som varierer litt avhengig om det er Vue eller React.

PropsTypeValidationDefaultDescription
isOpenbooleanPåkrevdfalseBestemmer om en spesifikk <AccordionItem> er åpen eller lukket
onToggleClick() [vue](id: string) => voidPåkrevd-Lar deg kontrollere åpne-lukke tilstanden til en spesifikk <AccordionItem> vha id.
onToggleClick() [react](e: React.MouseEvent, id: string) => voidPåkrevd-Lar deg kontrollere åpne-lukke tilstanden til en spesifikk <AccordionItem> vha id. React trenger at event sendes inn for å forhindre inkonsistent oppførsel.

I React, trenger man å sende inn event for å forhindre inkonsistent oppførsel. Dette er fordi <details>-elementet har sin egen innebygde toggle-funksjon som kan føre til inkonsistent 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.