Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Modal and accordion

A modal is a block on top of the page that asks for a response: confirm a deletion, fill in a form. An accordion is a list of sections where one is expanded. Both are built on x-show and one state property.

A modal

A confirmation for deleting a task. The modal is a dark backdrop covering the screen and a light box in the center:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<style>
  .backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.5); display: grid; place-items: center; }
  .dialog { background: Canvas; padding: 16px; border-radius: 8px; }
</style>
 
<div x-data="{ open: false }" style="min-height: 180px">
  <button @click="open = true">Delete task</button>
 
  <div
    x-show="open"
    x-transition.opacity
    class="backdrop"
  >
    <div class="dialog">
      <p>Delete "Buy milk"?</p>
      <button @click="open = false">Cancel</button>
    </div>
  </div>
</div>

The button opens the modal over the example, and "Cancel" closes it. x-show on the backdrop hides the backdrop and the box together.

Closing and the action

A good modal closes three ways: with a button, with the Esc key and with a click on the backdrop. The .self modifier fires only when the backdrop itself was clicked, not the box inside it:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<style>
  .backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.5); display: grid; place-items: center; }
  .dialog { background: Canvas; padding: 16px; border-radius: 8px; }
</style>
 
<div x-data="{
  open: false,
  remove() {
    console.log('Task deleted');
    this.open = false;
  }
}" @keydown.escape.window="open = false" style="min-height: 180px">
  <button @click="open = true">Delete task</button>
 
  <div
    x-show="open"
    x-transition.opacity
    @click.self="open = false"
    class="backdrop"
  >
    <div role="dialog" aria-modal="true" class="dialog">
      <p>Delete "Buy milk"?</p>
      <button @click="remove()">Delete</button>
      <button @click="open = false">Cancel</button>
    </div>
  </div>
</div>

"Delete" prints a message in the console and closes the modal; Esc and a click on the dark backdrop just close it. For full accessibility add x-trap="open" from the focus plugin — see the lesson on plugins.

An accordion

An accordion keeps the id of the open section. Clicking the open section closes it — the id becomes null:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{
  active: null,
  sections: [
    { id: 1, title: 'How do I add a task?', text: 'Type a title and press Enter.' },
    { id: 2, title: 'How do I mark it done?', text: 'Click the checkbox next to the task.' },
    { id: 3, title: 'Where are tasks stored?', text: 'In the browser, in localStorage.' }
  ]
}">
  <template x-for="section in sections" :key="section.id">
    <div style="border-bottom: 1px solid #ccc">
      <button @click="active = active === section.id ? null : section.id" x-text="section.title"></button>
      <p x-show="active === section.id" x-text="section.text"></p>
    </div>
  </template>
</div>

Clicking a question expands its answer and collapses the previous one. With the collapse plugin, add x-collapse to the paragraph to make it expand smoothly.

Common mistake

Closing the modal with a plain @click on the backdrop. Click events bubble: a click on the text or anywhere inside the box reaches the backdrop, and the modal closes although the user did not click outside. The .self modifier checks that the click was on the backdrop itself.

Thanks for reading!

Donate to the site — we work hard for you.