Вивчай
Домашнє завдання #12 · DOM-маніпуляції, події, модальні вікна та випадаючі меню
100 балів+15 бонусintermediate

Домашнє завдання #12: Модалка та dropdown для твого продукту

Твій продукт з ДЗ #5 досі був статичним. Сьогодні він уперше відреагує на користувача: ти створиш два UI-компоненти, які є буквально на кожному сайті — модальне вікно та dropdown меню. Але не абстрактні, а для своєї теми: у фільмотеці модалка може показувати деталі фільму, dropdown — обирати сортування. У колекції рецептів — «переглянути рецепт» і «фільтр за складністю». Механіка однакова, зміст — твій.


Що ти вже маєш

  • Стилізований лендінг свого продукту з ДЗ #6 — компоненти мають виглядати як його частина (кольори, шрифти, кнопки)

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


Файлова структура

hw-12/
├── index.html
├── style.css
├── script.js
└── screenshots/
    ├── desktop.png
    ├── mobile.png
    └── interaction.png

Частина 1: Модальне вікно

Кнопка на сторінці (наприклад, «Детальніше» на картці фільму) відкриває модалку поверх сторінки. Вигляд:

┌─────────────────────────────────────────┐
│ ░░░░░░░░░░░ затемнений фон ░░░░░░░░░░░ │
│ ░░░░┌───────────────────────────┐░░░░░ │
│ ░░░░│                       [✕] │░░░░░ │
│ ░░░░│  Назва фільму             │░░░░░ │
│ ░░░░│  Опис, рік, рейтинг...    │░░░░░ │
│ ░░░░│                           │░░░░░ │
│ ░░░░└───────────────────────────┘░░░░░ │
│ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ │
└─────────────────────────────────────────┘

Сценарії поведінки

Відкриття:

  • Користувач клікає на кнопку → модалка з'являється по центру екрана, фон за нею затемнюється
  • Поки модалка відкрита, сторінка під нею не прокручується (спробуй покрутити колесо миші — фон стоїть на місці)

Закриття — рівно три способи, і всі мають працювати:

  1. Клік на кнопку закриття (хрестик у кутку модалки)
  2. Клік на затемнений фон поза модалкою (клік по самій модалці її НЕ закриває!)
  3. Натискання клавіші Escape

Після закриття прокрутка сторінки знову працює.

Анімація:

  • Модалка з'являється плавно, а не «вистрибує»: фон поступово затемнюється, саме вікно трохи збільшується або з'їжджає згори
  • Анімація зроблена через CSS (transition + перемикання класів), а не через JavaScript-таймери

Частина 2: Dropdown меню

Мінімум три dropdown-кнопки з випадаючими списками. Придумай їх під свою тему: «Сортувати за…», «Жанр», «Рік» — або меню навігації.

[ Сортувати ▾ ]  [ Жанр ▾ ]  [ Рік ▾ ]
┌─────────────┐
│ За рейтингом │
│ За роком     │
│ За назвою    │
└─────────────┘

Сценарії поведінки

  • Клік на кнопку → під нею розкривається меню. Повторний клік — закривається
  • Взаємовиключність: відкритий може бути лише один dropdown. Відкриваєш другий → перший закривається сам
  • Клік будь-де поза dropdown (по фону сторінки) → усі відкриті меню закриваються
  • Клавіатура: коли фокус на кнопці — Enter або Space відкриває/закриває меню; Escape закриває відкрите меню
  • Меню з'являється з плавною анімацією (CSS)

Підказки

Рівень 1: напрямок думки
  • «Показати/сховати» у CSS — це перемикання класу на елементі. JavaScript лише додає/знімає клас, а вигляд описаний у стилях
  • Затемнений фон (overlay) — окремий елемент на весь екран, а модалка — його дочірній елемент. Тоді «клік по фону» і «клік по модалці» можна розрізнити
  • Для взаємовиключності dropdown подумай так: «перш ніж відкрити цей — закрий усі інші»
  • «Клік зовні» — це подія на всьому документі, у якій треба зрозуміти, чи стався клік усередині dropdown
Рівень 2: які інструменти використати
  • classList.add / remove / toggle — перемикання станів
  • Порівняння e.target з елементом overlay покаже, що клікнули саме по фону, а не по вмісту модалки
  • e.target.closest(селектор) поверне найближчого батька за селектором або null — так перевіряють «клік поза dropdown»
  • Подія keydown на document + перевірка e.key
  • Блокування прокрутки: клас з overflow: hidden на body
  • Плавне зникнення: opacity + transition + pointer-events: none (бо display: none не анімується). pointer-events: none робить схований елемент «прозорим» для кліків
Рівень 3: псевдокод
Модалка:
  клік на кнопку-відкриття:
    зняти клас "hidden" з overlay
    додати клас "no-scroll" на body
  функція closeModal:
    додати "hidden" на overlay
    зняти "no-scroll" з body
  клік на хрестик → closeModal
  клік на overlay → якщо ціль кліку — сам overlay → closeModal
  keydown на документі → якщо клавіша Escape → closeModal

Dropdown:
  клік на кнопку-toggle:
    для кожного dropdown, крім поточного → зняти клас "open"
    перемкнути "open" на поточному
  клік на документі:
    якщо у цілі кліку немає батька-dropdown → закрити всі
  keydown → якщо Escape → закрити всі

Бонус: фокус-пастка (+15)

Зроби модалку доступною з клавіатури по-дорослому — з фокус-пасткою:

  • Коли модалка відкривається, фокус переходить на перший інтерактивний елемент усередині неї
  • TabShift+Tab) циклічно ходить лише по елементах модалки й не виходить за її межі на сторінку під нею
  • Після закриття фокус повертається на кнопку, яка модалку відкрила

Саме так працюють модалки у великих продуктах — спробуй натиснути Tab у будь-якому діалозі GitHub.


Як здати

  1. Робота — у твоєму репозиторії курсу my-web-course, у папці hw-12/
  2. Мінімум 3 коміти з осмисленими повідомленнями (не "fix" і не "update") — чекер бачить git-історію
  3. У папці — README.md: 2-3 речення, що зроблено і як запустити
  4. Скріншоти в hw-12/screenshots/:
    • desktop.png — сторінка на ширині ~1440px
    • mobile.png — на ширині ~390px
    • interaction.pngвідкрита модалка по центру із затемненим фоном
  5. Надішли посилання на репозиторій (можна одразу на папку hw-12)

Критерії оцінки

КритерійТипБали
Модалка відкривається кнопкою і закривається всіма трьома способами (хрестик, клік по фону, Escape); клік по самій модалці її не закриває[поведінка]25
Прокрутка сторінки заблокована, поки модалка відкрита, і відновлюється після закриття[код]10
Поява модалки анімована через CSS transition і класи, без JS-таймерів[поведінка]10
На interaction.png модалка по центру, фон затемнений[скрін]10
Мінімум 3 dropdown, кожен відкривається/закривається кліком[поведінка]10
Відкритий може бути лише один dropdown одночасно[поведінка]10
Клік поза dropdown закриває всі відкриті меню[поведінка]10
Клавіатура: Enter/Space перемикає dropdown, Escape закриває[поведінка]10
Компоненти адаптовані під тему продукту та вписані в стиль лендінгу (desktop.png + mobile.png)[скрін]5
Бонус: фокус-пастка в модалці (Tab не виходить за межі, фокус повертається після закриття)[поведінка]+15

Що далі

У ДЗ #14 ти збереш головний інтерактивний проєкт блоку — каталог своєї колекції. Модалка та dropdown звідси стануть у пригоді й там, і в React-версії продукту — не видаляй код.