Summit.js
Docs UI Library Techniques Sponsors
Components

Accordion

An accordion stacks sections that expand and collapse in place. Each header is a real <button>, the chevron rotates through a class, and the panel below is revealed with s-show. The classic behavior is one section open at a time, which takes a single string of state.

One open at a time

Track which item is open as a string. Each trigger toggles: click the open one and it sets open back to empty; click a closed one and it takes over. Because only one value can match, opening a section closes whatever was open before.

Yes, every control is a real button.
Track an array instead of a single value.
Source
<div class="s-accordion" s-data="{ open: 'a' }">
  <div class="s-accordion-item">
    <button class="s-accordion-trigger" :class="{ 'is-open': open === 'a' }" @click="open = open === 'a' ? '' : 'a'">
      <span>Is it accessible?</span>
      <svg class="s-chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="s-accordion-panel" s-show="open === 'a'">Yes, every control is a real button.</div>
  </div>
  <div class="s-accordion-item">
    <button class="s-accordion-trigger" :class="{ 'is-open': open === 'b' }" @click="open = open === 'b' ? '' : 'b'">
      <span>Can I open many?</span>
      <svg class="s-chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="s-accordion-panel" s-show="open === 'b'">Track an array instead of a single value.</div>
  </div>
</div>

Allowing multiple open

To let several sections stay open at once, track an array of open ids instead of a single string. Each trigger toggles its own membership: if the id is already in the array, splice it out; otherwise push it in. The class check and the panel both test with includes.

Orders ship within two business days.
Return anything within thirty days.
Source
<div class="s-accordion" s-data="{ open: ['a'] }">
  <div class="s-accordion-item">
    <button class="s-accordion-trigger" :class="{ 'is-open': open.includes('a') }" @click="open.includes('a') ? open.splice(open.indexOf('a'), 1) : open.push('a')">
      <span>Shipping</span>
      <svg class="s-chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="s-accordion-panel" s-show="open.includes('a')">Orders ship within two business days.</div>
  </div>
  <div class="s-accordion-item">
    <button class="s-accordion-trigger" :class="{ 'is-open': open.includes('b') }" @click="open.includes('b') ? open.splice(open.indexOf('b'), 1) : open.push('b')">
      <span>Returns</span>
      <svg class="s-chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m6 9 6 6 6-6"/></svg>
    </button>
    <div class="s-accordion-panel" s-show="open.includes('b')">Return anything within thirty days.</div>
  </div>
</div>

Notes

  • Every trigger is a real button, so it is keyboard reachable and toggles with Enter or Space without extra wiring.
  • The .s-chevron rotates on its own through the is-open class in components.css; you only bind the class, never the transform.
  • Start open at an id (or seed the array) to have a section expanded on first render, or set it to '' (or []) to begin fully collapsed.

For swapping between panels rather than stacking them, see Tabs. The whole set is on the overview.

Esc
Loading search...
Recent
Suggested
No results for "".
↑↓ to navigate ↵ to select esc to close