7.2 KiB
🎨 Использование UI компонентов: Выпадающие списки (Dropdowns)
В проекте Magistr используется премиальная кастомная дизайн-система выпадающих списков. В связи с ограничениями браузеров на стилизацию стандартных элементов <select>, мы реализовали два типа компонентов, которые выглядят потрясающе (с эффектом glassmorphism, встроенными микро-анимациями и свечением), но интегрируются максимально просто.
1. Стандартные одинарные списки (Custom Select Wrapper)
Этот компонент автоматически "оборачивает" любые стандартные теги <select> на всём сайте, превращая их в красивые выпадающие меню. Вам не нужно писать сложный HTML, всё работает автоматически!
Как добавить новый одинарный список:
Просто добавьте обычный тег <select> в HTML:
<div class="form-group">
<label for="my-new-select">Выберите опцию</label>
<select id="my-new-select">
<option value="">Выберите...</option>
<option value="1">Опция 1</option>
<option value="2">Опция 2</option>
</select>
</div>
Как это работает:
- В файле
frontend/admin/js/dropdown.jsинициализируется глобальныйMutationObserver. - Как только любой скрипт или загрузка страницы добавляет
<select>в DOM, скрипт автоматически:- Скрывает оригинальный
<select>(но оставляет его доступным из JS!). - Рисует поверх него красивый
div.custom-select-wrapperс нужным текстом, иконкой-шевроном и эффектом размытия фона. - Синхронизирует состояния (если вы выберете элемент в кастомном UI, он автоматически изменит
select.valueи кинет событиеchange).
- Скрывает оригинальный
Динамическое обновление списка (через JS):
Если вы подгружаете список с API, просто обновите innerHTML нативного селекта, как обычно:
const select = document.getElementById('my-new-select');
select.innerHTML = '<option value="99">Новое значение с API</option>';
Магия! Экземпляр CustomSelect использует свой собственный внутренний MutationObserver для отслеживания изменений <option>, поэтому он автоматически перестроит красивый кастомный выпадающий список. Никаких дополнительных вызовов для перерисовки не требуется.
2. Множественный выбор (Multi-Select с чекбоксами)
Этот UI-компонент позволяет выбирать сразу несколько элементов из выпадающего списка. Он включает в себя кастомные красивые галочки (checkmarks) с неоновой подсветкой и кастомный скроллбар.
Этот компонент требует написания определённой HTML-структуры, так как нативного тега select multiple с похожей функциональностью не существует.
Как добавить мульти-селект:
1. HTML Структура:
<div class="form-group">
<label>Выберите оборудование</label>
<div class="custom-multi-select">
<!-- Кнопка-триггер (то, на что нажимаем) -->
<div class="select-box" id="my-multi-box">
<span class="select-text" id="my-multi-text">Выберите...</span>
<svg class="dropdown-icon" width="12" height="8" viewBox="0 0 12 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 1.5L6 6.5L11 1.5" stroke="#9ca3af" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<!-- Само выпадающее меню -->
<div class="dropdown-menu" id="my-multi-menu">
<div id="my-multi-checkboxes" class="checkbox-group-vertical">
<!-- Сюда JS добавит чекбоксы -->
</div>
</div>
</div>
</div>
2. Инициализация (в вашем JS-файле):
Используйте готовую утилиту initMultiSelect из utils.js (она обрабатывает клики и открытие/закрытие):
import { initMultiSelect } from '../utils.js';
// Передаем ID: box, menu, text, container
initMultiSelect('my-multi-box', 'my-multi-menu', 'my-multi-text', 'my-multi-checkboxes');
3. Рендеринг элементов с кастомными галочками:
Чтобы нарисовать сами чекбоксы, нужно использовать класс .checkbox-item и обязательный пустой span.checkmark. Пример генерации HTML:
const container = document.getElementById('my-multi-checkboxes');
const items = [{id: 1, name: "Проектор"}, {id: 2, name: "Компьютер"}];
container.innerHTML = items.map(item => `
<label class="checkbox-item">
<input type="checkbox" value="${item.id}">
<!-- Обязательный элемент для красивой галочки: -->
<span class="checkmark"></span>
<span class="checkbox-label">${item.name}</span>
</label>
`).join('');
Как прочитать выбранные значения:
Просто соберите массив value у выбранных чекбоксов внутри контейнера:
const checkedBoxes = Array.from(document.querySelectorAll('#my-multi-checkboxes input:checked'));
const selectedIds = checkedBoxes.map(chk => parseInt(chk.value, 10));
console.log(selectedIds); // [1, 2]
Итог и правила
- Никогда не пытайтесь "красить" нативные теги
<option>. Браузеры (особенно Safari и Chrome) не позволяют этого сделать. - Для отдельного выбора (1 из N) всегда используйте стандартный
select. Наша обёртка сделает всю магию сама. - Для множественного выбора (N из M) используйте HTML-шаблон
.custom-multi-select(сspan.checkmark).