Encodera

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

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

Оглавление

Выпадающее меню и вкладки

Выпадающее меню и вкладки встречаются почти на каждом сайте. На Alpine оба собираются из уже знакомых директив: одно свойство в x-data, x-show для видимости и @click для переключения. Оба элемента — часть страницы списка дел в index.html.

Выпадающее меню

Меню действий над задачей. Минимальная версия — кнопка и список, который открывается по клику:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{ open: false }">
  <button @click="open = !open">Действия</button>
  <ul x-show="open">
    <li>Изменить</li>
    <li>Удалить</li>
  </ul>
</div>

Кнопка открывает и закрывает список. Но меню пока закрывается только повторным кликом по кнопке.

Закрытие снаружи и по Esc

Пользователь ждёт, что меню закроется по клику в любом другом месте и по клавише Esc:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<div x-data="{ open: false }" @keydown.escape.window="open = false" style="position: relative; display: inline-block">
  <button @click="open = !open" :aria-expanded="open">Действия ▾</button>
 
  <ul
    x-show="open"
    x-transition.opacity
    @click.outside="open = false"
    style="position: absolute; margin: 4px 0; padding: 4px 12px; border: 1px solid #ccc; background: Canvas; list-style: none"
  >
    <li><button @click="console.log('Изменить'); open = false">Изменить</button></li>
    <li><button @click="console.log('Удалить'); open = false">Удалить</button></li>
  </ul>
</div>

Меню закрывается кликом мимо него, клавишей Esc и после выбора пункта, а выбранное действие появляется в консоли. Атрибут aria-expanded сообщает программам чтения с экрана, открыто ли меню.

Вкладки

Вкладки хранят имя активной вкладки. Кнопка меняет его, панель показывается, когда имя совпадает:

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
 
<style>
  .tab-active { font-weight: bold; text-decoration: underline; }
</style>
 
<div x-data="{ tab: 'active' }">
  <nav>
    <button @click="tab = 'active'" :class="{ 'tab-active': tab === 'active' }">Активные</button>
    <button @click="tab = 'done'" :class="{ 'tab-active': tab === 'done' }">Выполненные</button>
  </nav>
 
  <div x-show="tab === 'active'">
    <p>Купить молоко</p>
    <p>Позвонить Олегу</p>
  </div>
  <div x-show="tab === 'done'">
    <p>Оплатить интернет</p>
  </div>
</div>

Сначала открыта вкладка «Активные» с двумя задачами. Кнопка «Выполненные» переключает панель и выделяет себя жирным.

Если вкладок много, их описывают массивом и выводят кнопки через x-for — тогда новая вкладка добавляется одной строкой данных.

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

Написать @keydown.escape без .window. Событие клавиатуры приходит элементу, на котором стоит фокус. А в Safari клик по кнопке не переводит на неё фокус: меню открыто, фокус остаётся на <body>, и Esc без .window ничего не закрывает. Модификатор .window слушает клавишу на всём окне, поэтому меню закрывается всегда.

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

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