Модальное окно и аккордеон
Модальное окно — блок поверх страницы, который требует ответа: подтвердить удаление, заполнить форму. Аккордеон — список разделов, из которых раскрыт один. Оба строятся на 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 проверяет, что клик был именно по фону.