В наши дни одним из наших любимых технологических стеков здесь, в Mindvalley, является Phoenix, Elixir, TailwindCSS, AlpineJS и LiveView, также известный как стек PETAL. Он получил много положительных отзывов от членов сообщества Elixir и не зря.

Стек PETAL позволяет инженерам создавать красивые, интерактивные и оптимизированные по производительности приложения за короткое время и с минимальными усилиями.

Хотя Elixir, Phoenix и Liveview напрямую зависят друг от друга (вы не можете использовать LiveView вне контекста приложения Phoenix), TailwindCSS и AlpineJS - это независимые библиотеки, которые могут работать вместе практически с любым языком веб-программирования.

Другими словами, инженер, работающий с Programming Language A, может решить проблему с помощью TailwindCSS и AlpineJS и легко повторно использовать код в другом проекте, написанном на Programming Language B.

В сегодняшней статье я хочу продемонстрировать мощь TailwindCSS и AlpineJS путем реализации модального окна всего с 12 СТРОКАМИ КОДА !!!

Предпосылки

Вы можете использовать любой язык программирования / фреймворк в качестве основы. Что касается настройки TailwindCSS и AlpineJS, вы можете ознакомиться с документацией по установке в качестве ориентира:

Боковое примечание: это не учебник TailwindCSS или AlpineJS. Если вы не знакомы с этими двумя библиотеками, вы все равно можете прочитать это сообщение в блоге, но я предлагаю вам обращаться к официальной документации, когда вы сочтете нужным.

Модальное поведение

Прежде чем приступить к написанию кода, важно определить ожидаемое поведение. Любое модальное окно имеет следующие характеристики:

  • Триггерный элемент - модальные окна появляются не на пустом месте. Они появляются на экране после определенного действия.
  • Оверлей - полупрозрачный слой, закрывающий главную страницу. Его цель - привлечь внимание пользователя к содержанию модального окна.
  • Модальное содержимое - центральная часть модального окна; обычно он содержит различные элементы HTML и CTA (призыв к действию) в виде кнопки. В большинстве случаев, когда пользователь выполняет CTA, модальное окно закрывается, и фокус возвращается на главную страницу.

Ниже вы можете найти образец GIF, иллюстрирующий пользовательский интерфейс модального окна и поведение, которое мы собираемся реализовать.

ШАГ 1. Создайте триггерный элемент

Нашим триггерным элементом будет простая кнопка с серым фоном, белым текстом и цветовым эффектом, изменяющимся при наведении курсора:

<button class="px-4 py-2 bg-gray-400 hover:bg-gray-700 text-white text-xl font-serif rounded-full border-none focus:outline-none">Open Modal</button>

Этот код поместит кнопку в левый верхний угол нашей страницы. В идеале мы хотели бы изменить это и вместо этого расположить элемент в центре. Такого поведения легко добиться, заключив нашу кнопку в div и применив пару классов TailwindCSS для настройки параметра отображения.

<div class="flex items-center justify-center mt-80">
  <button class="px-4 py-2 bg-gray-400 hover:bg-gray-700 text-white text-xl font-serif rounded-full border-none focus:outline-none">Open Modal</button>
</div>

ШАГ 2: Создание модального окна

Отдельный элемент DIV будет представлять модальное окно, и он будет иметь следующие характеристики (которые соответствуют определенным классам TailwindCSS)

  • Он должен занимать всю страницу - fixed, w-full, h-full, top-0, left-0
  • Он должен появиться поверх элемента кнопки - z-1
  • Его дочерние элементы должны быть центрированы - flex items-center justify-center

В сочетании новый код выглядит так:

<div class="flex items-center justify-center mt-80">
  <button class="px-4 py-2 bg-gray-400 hover:bg-gray-700 text-white text-xl font-serif rounded-full border-none focus:outline-none">Open Modal</button>
  <div class="fixed z-1 w-full h-full top-0 left-0 flex items-center justify-center"></div>
</div>

У родительского DIV будет два дочерних элемента:

  1. Полупрозрачный серый оверлей занимает всю страницу.
<div class="fixed w-full h-full bg-gray-500 opacity-50"></div>

2. Основное модальное содержимое с белым фоном и закругленными краями появляется в центре страницы. Он имеет простое однострочное сообщение и красную кнопку с призывом к действию.

<div class="relative z-2 w-3/12 bg-white p-8 mx-auto rounded-xl flex flex-col items-center">
  <p class="text-xl font-serif pb-4">
    Hello world, I am a free modal :)
  </p>
  <button class="px-4 py-2 bg-red-400 hover:bg-red-700 text-white text-xl font-serif rounded-full border-none focus:outline-none">
    Close Modal
  </button>
</div>

Когда мы сложим все части вместе, мы получим следующий пример кода:

<div class="flex items-center justify-center mt-80">
  <button class="px-4 py-2 bg-gray-400 hover:bg-gray-700 text-white text-xl font-serif rounded-full border-none focus:outline-none">Open Modal</button>
  <div class="fixed z-1 w-full h-full top-0 left-0 flex items-center justify-center">
    <div class="fixed w-full h-full bg-gray-500 opacity-50"></div>
    <div class="relative z-2 w-3/12 bg-white p-8 mx-auto rounded-xl flex flex-col items-center">
      <p class="text-xl font-serif pb-4">Hello world, I am a free modal :)</p>
      <button class="px-4 py-2 bg-red-400 hover:bg-red-700 text-white text-xl font-serif rounded-full border-none focus:outline-none">Close Modal</button>
    </div>
  </div>
</div>

Обратите внимание на классы TailwindCSS z-1 и z-2. Благодаря им мы можем правильно расположить наши элементы на странице. Модальное содержимое появится поверх серого оверлея, который закроет главную страницу.

ШАГ 3: Кодирование модального поведения

Пришло время появиться AlpineJS. Мы будем использовать его возможности для управления потоком отображения и скрытия модального окна.

Прежде всего, мы объявим новую область видимости компонента с помощью директивы x-data. Мы добавим его к родительскому элементу DIV и инициализируем логическую переменную, представляющую модальное состояние.

Поскольку мы не хотим отображать модальное окно при загрузке страницы, мы установим для логического значения значение false.

<div class="flex items-center justify-center mt-80" 
  x-data="{ open: false }">
  ...
</div>

Затем мы будем использовать директивы @click и @click.away, чтобы контролировать, когда мы хотим открывать и закрывать модальное окно.

<div class="flex items-center justify-center mt-80"
  x-data="{ open: false }">
  <button class="px-4 py-2 bg-gray-400 hover:bg-gray-700 text-white text-xl font-serif rounded-full border-none focus:outline-none"
  @click="open = true">Open Modal</button>
  <div class="fixed z-1 w-full h-full top-0 left-0 flex items-center justify-center" x-cloak x-show="open">
    <div class="fixed w-full h-full bg-gray-500 opacity-50"></div>
    <div class="relative z-2 w-3/12 bg-white p-8 mx-auto rounded-xl flex flex-col items-center" @click.away="open = false">
      <p class="text-xl font-serif pb-4">Hello world, I am a free modal :)</p>
      <button class="px-4 py-2 bg-red-400 hover:bg-red-700 text-white text-xl font-serif rounded-full border-none focus:outline-none" @click="open = false">Close Modal</button>
    </div>
  </div>
</div>

Наконец, нам нужно обратиться к директивам x-cloak и x-show. Добавление их в модальное окно гарантирует, что оно будет правильно отображаться в соответствии с правилами, которые мы установили выше.

Если вы хотите узнать больше об AlpineJS, я предлагаю вам проверить репозиторий Github - https://github.com/alpinejs/alpine.

Вывод

И вуаля, мы закончили. Нам удалось создать модальное окно, написав всего 12 строк кода.

Вот хорошая идея на Github, демонстрирующая финальную версию кода:

Конечно, это всего лишь образец реализации. На самом деле, при написании производственного кода вам, вероятно, понадобится модальное окно, поддерживающее более сложные сценарии.

Тем не менее, если вы понимаете базовую механику модального кода, вы легко сможете расширить предлагаемую реализацию в соответствии со своими потребностями.