8pt

Accordion

Accordion•Disclosure
Overview

A single-open accordion: the plus rotates into a cross and content fades in. Fully keyboard accessible.

Plain HTML, CSS and a little vanilla JS, with no framework dependency. Copy the prompt into Claude Code, Cursor, Trae or Codex and the model adds Accordion to your project in your colors.

Where to use it

FAQs, accordions, expandable explanations and grouped settings.

Install

With Builder, install it with the 8pt CLI or call it directly from an editor connected to 8pt MCP.

$ npm i -g @8pt-dev/cli && 8pt add accordion
mcp › Use 8pt MCP to call get_component("accordion")

Code

Source for Accordion. Motion uses only transform and opacity and respects the Reduce motion setting.

<div class="x-acc">
  <div class="x-acc__item open"><button type="button" aria-expanded="true">What is the 8pt grid?<i></i></button><div class="x-acc__panel"><div><p>Every size is a multiple of 8, so the interface keeps one rhythm.</p></div></div></div>
  <div class="x-acc__item"><button type="button" aria-expanded="false">Why 8?<i></i></button><div class="x-acc__panel"><div><p>Divides cleanly at common screen densities, so scaling never lands on half pixels.</p></div></div></div>
  <div class="x-acc__item"><button type="button" aria-expanded="false">What about values under 8?<i></i></button><div class="x-acc__panel"><div><p>Use 4 as a half step for fine-tuning icons and text.</p></div></div></div>
</div>
.x-acc{width:min(420px,100%);max-width:100%;color:var(--d-fg,#fff)}
.x-acc__item{border-bottom:1px solid var(--d-line,rgba(255,255,255,.1))}
.x-acc__item button{display:flex;align-items:center;justify-content:space-between;width:100%;padding:16px 2px;border:0;background:transparent;color:inherit;font:600 15px/1.3 var(--d-font,system-ui,sans-serif);text-align:left;cursor:pointer}
.x-acc__item button i{position:relative;width:12px;height:12px;flex:none;transition:transform .35s cubic-bezier(.2,.9,.2,1)}
.x-acc__item button i::before,.x-acc__item button i::after{content:"";position:absolute;left:0;top:5px;width:12px;height:2px;border-radius:2px;background:currentColor}
.x-acc__item button i::after{transform:rotate(90deg)}
.x-acc__item.open button i{transform:rotate(45deg)}
.x-acc__panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .35s cubic-bezier(.2,.9,.2,1)}
.x-acc__panel>div{overflow:hidden}
.x-acc__panel p{margin:0;padding:0 2px 16px;font:14px/1.65 var(--d-font,system-ui,sans-serif);color:var(--d-muted,#a0a0ab);opacity:0;transform:translateY(-4px);transition:opacity .3s,transform .35s}
.x-acc__item.open .x-acc__panel{grid-template-rows:1fr}
.x-acc__item.open .x-acc__panel p{opacity:1;transform:none}
const init = (root) => {
  const items = root.querySelectorAll('.x-acc__item');
  items.forEach(it => it.querySelector('button').addEventListener('click', () => {
    const open = !it.classList.contains('open');
    items.forEach(o => { o.classList.remove('open'); o.querySelector('button').setAttribute('aria-expanded', 'false'); });
    if (open) { it.classList.add('open'); it.querySelector('button').setAttribute('aria-expanded', 'true'); }
  }));
};
Subscribe to Builder to see the full source.See pricing

More components

View all

AI Prompt Composer

Film Strip Carousel

Auto Tab Showcase

Media Bento Grid

Agent Chat Window

Model Pill Marquee

Director Art Cards

Mac File Window

Keep exploring