Components

Accordion

Built on <details>. Opening, closing and keyboard support come from the browser: this component is pure CSS, with no script at all.

What is Perfect UI?

A lightweight CSS and JavaScript library.

Does it need JavaScript?

Only to emulate what a browser is missing.

One open at a time

Give the items the same name. The browser closes the others for you:

First question

First answer

Second question

Second answer

Open by default

Open on load

Content

One block

Consecutive items share the line between them, and only the outer corners stay round โ€” an accordion reads as one block, not as a stack of cards. Nothing to add: this is what the first example already does. A lone item keeps all four corners, since it is both the first child and the last.

Spacing them apart instead is two rules of your own:

.accordion-spaced {
  gap: var(--pui-space);
}
.accordion-spaced > .pui-accordion-item {
  margin-block-start: 0;
  border-radius: var(--pui-radius);
}

Marking the open item

pui-highlighted on the container gives the expanded item the same background as a card header, so a long list shows where you are. It replaces v0's accordion-accented:

Expanded

This item carries the band.

Collapsed

This one does not.

For a different tone, one rule of your own is enough โ€” --pui-bg-emphasis is there for a third level:

.pui-accordion.pui-highlighted > .pui-accordion-item[open] {
  background-color: var(--pui-bg-emphasis);
}

Your own icon

Put an element with pui-accordion-icon in the summary and the drawn chevron steps aside. Placement and the rotation on open stay with the library:

Question

Answer

Anything works โ€” an icon font, an inline <svg>, or a character.

Reacting to it

<details> fires a toggle event, and open is a property:

document
  .querySelector(".pui-accordion-item")
  .addEventListener("toggle", (event) => {
    console.log(event.target.open);
  });