Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Модальное окно и аккордеон

Модальное окно — блок поверх страницы, который требует ответа: подтвердить удаление, заполнить форму. Аккордеон — список разделов, из которых раскрыт один. Оба строятся на x-show и одном свойстве состояния.

Модальное окно

Подтверждение удаления задачи. Окно состоит из затемнённого фона на весь экран и белого блока в центре:

<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">Удалить задачу</button>
 
  <div
    x-show="open"
    x-transition.opacity
    class="backdrop"
  >
    <div class="dialog">
      <p>Удалить «Купить молоко»?</p>
      <button @click="open = false">Отмена</button>
    </div>
  </div>
</div>

Кнопка открывает окно поверх примера, «Отмена» закрывает его. x-show на фоне прячет и фон, и окно разом.

Закрытие и действие

Хорошее модальное окно закрывается тремя способами: кнопкой, клавишей Esc и кликом по фону. Модификатор .self срабатывает, только если кликнули по самому фону, а не по окну внутри:

<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('Задача удалена');
    this.open = false;
  }
}" @keydown.escape.window="open = false" style="min-height: 180px">
  <button @click="open = true">Удалить задачу</button>
 
  <div
    x-show="open"
    x-transition.opacity
    @click.self="open = false"
    class="backdrop"
  >
    <div role="dialog" aria-modal="true" class="dialog">
      <p>Удалить «Купить молоко»?</p>
      <button @click="remove()">Удалить</button>
      <button @click="open = false">Отмена</button>
    </div>
  </div>
</div>

«Удалить» печатает сообщение в консоль и закрывает окно; Esc и клик по тёмному фону просто закрывают. Для полноценной доступности добавьте x-trap="open" из плагина focus — урок о плагинах.

Аккордеон

В аккордеоне хранят номер открытого раздела. Клик по открытому разделу закрывает его — номер становится 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: 'Как добавить задачу?', text: 'Введите название и нажмите Enter.' },
    { id: 2, title: 'Как отметить выполненной?', text: 'Нажмите на чекбокс рядом с задачей.' },
    { id: 3, title: 'Где хранятся задачи?', text: 'В браузере, в 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>

Клик по вопросу раскрывает ответ и сворачивает предыдущий. С плагином collapse добавьте x-collapse к абзацу — раскрытие станет плавным.

Частая ошибка

Закрывать окно обычным @click на фоне. Событие клика всплывает: клик по тексту или любому месту внутри окна дойдёт до фона, и окно закроется, хотя пользователь кликнул не мимо. Модификатор .self проверяет, что клик был именно по фону.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.