Web Awesome: компоненты для веб-сервисов — 9 интерфейсов и мастерская
Собираем кабинет и CRM из бесплатных компонентов: девять живых интерфейсов, настройки, исходный код, формы, фильтры, диалоги и адаптивная рабочая область.

У личного кабинета, CRM и внутреннего сервиса много общих деталей: поля, вкладки, диалоги, фильтры, дерево документов и состояния кнопок. Пользователь ожидает, что они будут работать согласованно. Если в одном разделе Escape закрывает окно, а в другом нет, или одинаковые поля выглядят по-разному, даже небольшой сервис становится труднее освоить.
Web Awesome помогает собрать такие элементы из готовых Web Components. В этой статье разберём бесплатную Core-версию 3.14.0 и девять полноценных сцен интерфейса. Все примеры можно попробовать на странице, посмотреть их HTML и JavaScript, скачать и запустить у себя. Покажем не только разметку, но и поведение: что происходит с данными, как отменить действие и как перенести экран в настоящее приложение.
Что такое Web Awesome и какой результат он даёт
Web Awesome — набор пользовательских HTML-элементов: например, <wa-input>, <wa-dialog> и <wa-tab-group>. После подключения JavaScript браузер знает, как отображать эти теги и как они должны реагировать на взаимодействие. Разработчик собирает экран из компонентов, связывает их с данными и определяет бизнес-правила.
Для пользователя результат выглядит как обычный интерфейс. Он вводит имя, открывает фильтры, переключает вкладку и получает понятную обратную связь. Ему не нужно знать, что внутри используется Shadow DOM или библиотека Lit. Эти технические детали важны разработчику, когда он настраивает оформление и связывает компоненты с событиями приложения.
Наша мастерская — самостоятельный проект на HTML5 и JavaScript. Bootstrap 5.3.8 отвечает за сетку и внешнюю панель настроек, а Web Awesome — за элементы внутри живых сцен. React, Vue и Angular здесь не требуются. Такой формат удобно встроить в PHP-сайт или использовать как отдельный прототип будущего сервиса.
Документация: установка и способы подключения.
Где применять и когда достаточно обычного HTML
Хороший первый кандидат — внутренний кабинет с несколькими формами и повторяющимися действиями. В нём важнее последовательное поведение, чем уникальный внешний вид каждой кнопки. Готовые компоненты помогают быстро собрать экран настроек, панель фильтров или карточку клиента, а затем уделить время настоящим данным и сообщениям об ошибках.
Другой сценарий — постепенное улучшение существующего сайта. Не обязательно переписывать весь frontend: можно начать с одной формы или отдельного инструмента. При этом стоит заранее определить, кто отвечает за общую сетку, типографику и цвета. Если бессистемно смешать три набора компонентов, пользователь увидит несколько несовместимых визуальных языков.
Для простой страницы с двумя полями и одной кнопкой нативный HTML часто достаточен. Библиотека оправдана, когда повторное использование и согласованность окупают дополнительный JavaScript. Например, вместо сложного дерева для пяти плоских ссылок разумнее оставить список. Выбирайте компонент по задаче, а не ради демонстрации всех возможностей сразу.
Мини-мастерская: девять интерфейсов, которые можно попробовать
Выберите сцену в верхнем списке. Под заголовком написано, где такой экран полезен и что именно следует попробовать. Внешний переключатель акцента меняет цвет компонентов, а сброс возвращает начальные данные выбранной сцены. Смена примера также очищает его учебное состояние — это специально обозначено под рабочей областью.
В мастерской работают профиль, фильтры заявок, подтверждение архивирования, вкладки клиента, дерево документов, калькулятор команды, обратная связь, разделяемая рабочая область и чек-лист. Это разные задачи: часть связана с вводом данных, часть — с навигацией, часть — с управлением последствиями действия. Не ограничивайтесь первым успешным нажатием: попробуйте пустое имя, отмену фильтра и возврат из диалога.
Все данные вымышленные и остаются в памяти вкладки. Отправка письма, списание денег и изменение серверного проекта не выполняются. При этом сами компоненты и прикладная логика настоящие: фильтр действительно отбирает карточки, FormData собирает значения, а расчёт меняет итог. После опыта раскройте исходник и скачайте выбранный пример или весь проект.
Бесплатные компоненты, версия и сборка без CDN
В проекте закреплена Web Awesome 3.14.0. Используются только бесплатные компоненты Core. Платные компоненты и готовые Pro-паттерны для повторения мастерской не нужны. Перед добавлением нового элемента сверяйте его карточку в официальном каталоге: возможности пакета и лицензия конкретного продукта могут различаться.
Важна воспроизводимость. package.json задаёт версии прямых зависимостей, а package-lock.json фиксирует дерево установки. Команда npm ci восстанавливает его; npm run build собирает используемые компоненты и стили в public/vendor. В опубликованной мастерской библиотека загружается с того же сайта, а не с внешнего CDN.
В исходниках импортируются конкретные компоненты и русская локализация. Это позволяет видеть состав решения. Не подменяйте установленную версию непроверенным latest в каждом HTML: обновление зависимости должно быть отдельным изменением с проверкой формы, диалога и экспорта. Старые примеры Shoelace тоже нельзя переносить простой заменой префикса тега — API нужно сверять.
npm install --save-exact @awesome.me/webawesome@3.14.0
npm ci
npm run build
Документация: каталог бесплатных и Pro-компонентов.
Как связаны теги, свойства, события и Shadow DOM
У компонента есть HTML-атрибуты и JavaScript-свойства. Начальную подпись удобно задать атрибутом label, а текущее состояние переключать свойством объекта: например, dialog.open = true. Для логики используйте документированный публичный API. Поиск внутренних кнопок в shadowRoot создаёт зависимость от устройства компонента, которое может измениться после обновления.
Shadow DOM отделяет внутреннюю разметку и стили от внешней страницы. Поэтому правило для обычного input не обязано изменить поле внутри wa-input. Для оформления предусмотрены CSS-переменные и открытые части через ::part. Начинайте с них, а не с попытки пробить внутреннюю структуру произвольными селекторами.
Есть и момент готовности. Разметка может появиться раньше, чем браузер зарегистрирует пользовательский тег. Перед чтением формы и подключением сценария мастерская ждёт определения компонентов. Если сцена переключилась во время ожидания, номер её ревизии не позволяет старой инициализации подключить обработчики к новому экрану. Такой подход полезен и для ленивой загрузки в рабочем приложении.
import '@awesome.me/webawesome/dist/components/dialog/dialog.js';
await customElements.whenDefined('wa-dialog');
const dialog = document.querySelector('#confirm');
document.querySelector('#open').addEventListener('click', () => {
dialog.open = true;
});
Пример 1. Профиль: обязательность, email и FormData
Форма профиля объединяет имя, рабочую почту, роль и переключатель сводки. Сначала очистите имя и нажмите сохранение: обязательное поле должно помешать переходу к результату. Затем заполните его и посмотрите JSON-квитанцию. Так видно, что собирается из формы и почему подпись поля и его name решают разные задачи.
Label объясняет человеку, что вводить. Name определяет ключ в FormData. Value хранит значение. Переключатель отправляет значение только в выбранном состоянии, поэтому отсутствие ключа тоже нужно учитывать. На сервере нельзя без проверки считать, что каждая ожидаемая строка обязательно присутствует или имеет правильный тип.
Поле роли здесь учебное. В настоящем кабинете сервер обязан отдельно решить, кому разрешено менять роли. Также потребуются сохранение, сообщение об ошибке, индикатор незавершённых изменений и защита от повторного нажатия во время запроса. Компонент делает ввод удобнее, но не принимает за приложение эти решения.
<form id="profile">
<wa-input label="Имя" name="name" required></wa-input>
<wa-input label="Рабочая почта" name="email" type="email" required></wa-input>
<wa-switch name="digest" value="yes">Получать сводку</wa-switch>
<wa-button type="submit" variant="brand">Сохранить</wa-button>
</form>
form.addEventListener('submit', event => {
event.preventDefault();
const payload = Object.fromEntries(new FormData(form));
output.textContent = JSON.stringify(payload, null, 2);
});
Документация: пользовательские элементы, связанные с формой.
Пример 2. Боковые фильтры и понятная отмена
В каталоге или CRM фильтры могут занимать слишком много места. Боковая панель позволяет оставить список главным содержимым, а настройки показывать по запросу. В нашем примере статус и признак срочности отбирают пять учебных заявок. Комбинация «В работе» и «Только срочные» оставляет одну карточку.
Пример разделяет черновик выбора и применённые условия. Пока панель открыта, человек может менять поля. Кнопка применения обновляет список, а отмена закрывает панель без изменения результата. При следующем открытии поля восстанавливаются из применённых значений. Иначе пользователь увидел бы настройки, которые не соответствуют карточкам на экране.
В рабочем сервисе этот же принцип можно связать с URL: применённые фильтры становятся параметрами запроса и сохраняются при обновлении страницы. При серверной загрузке добавьте состояние ожидания, пустую выдачу и ошибку. Не показывайте старый счётчик как результат нового фильтра, пока ответ ещё не пришёл.
openButton.addEventListener('click', () => {
statusField.value = applied.status;
urgentSwitch.checked = applied.urgent;
drawer.open = true;
});
applyButton.addEventListener('click', () => {
applied = { status: statusField.value, urgent: urgentSwitch.checked };
renderFilteredRows(applied);
drawer.open = false;
});
Документация: drawer, размер и расположение панели.
Пример 3. Диалог подтверждения и восстановление
Подтверждение должно объяснять конкретное действие. Поэтому заголовок называет проект, а текст описывает последствие и возможность возврата. Кнопки «Оставить активным» и «Подтвердить архивирование» понятнее абстрактных «Нет» и «Да». Человеку не приходится повторно читать вопрос, чтобы понять смысл выбора.
В мастерской подтверждение меняет состояние учебной карточки и доступность действий. После архивирования становится доступно восстановление. Escape закрывает окно без архивирования. Это полезная последовательность для проверки: открыть, отказаться, открыть повторно, подтвердить, вернуть объект. Она показывает больше, чем единственный успешный клик.
В реальном приложении не объявляйте объект архивированным до подтверждения сервера, если не реализована продуманная оптимистическая схема. При ошибке оставьте человеку его контекст и возможность повторить запрос. После закрытия важно вернуть фокус в подходящее место, особенно если исходная кнопка стала недоступной или исчезла.
В этой сцене после архивирования исходная кнопка отключается. Фокус переносится на «Вернуть проект» по событию wa-after-hide: к этому моменту завершён переход и фон уже доступен. Немедленный вызов focus после open=false слишком ранний, поскольку модальное окно закрывается асинхронно. При удалении сцены этот обработчик отключается.
<wa-dialog id="confirm" label="Архивировать проект «Север»?">
<p>Проект можно будет вернуть из архива.</p>
<wa-button slot="footer" data-dialog="close">Оставить активным</wa-button>
<wa-button slot="footer" id="confirm-archive" variant="danger">
Подтвердить архивирование
</wa-button>
</wa-dialog>
Документация: диалог, закрытие и начальный фокус.
Пример 4. Вкладки карточки клиента
Вкладки подходят для нескольких представлений одного объекта: основные сведения, история и заметки клиента. В примере они не создают новые страницы и не теряют введённую заметку при обычном переключении. Это помогает сравнить контекст и продолжить работу без постоянного возвращения назад.
Не прячьте во вкладках последовательные шаги обязательной процедуры. Если человеку нужно сначала заполнить данные, затем проверить и подтвердить, обычно лучше пошаговая форма. Вкладки предполагают, что разделы можно выбирать в произвольном порядке. Также не стоит размещать в одной панели действие, меняющее данные другой, без заметного сообщения о результате.
Для большого приложения решите, должна ли активная вкладка отражаться в URL и что загружать заранее. История на тысячу записей может открываться отдельно от основной карточки. В такой ситуации важно различать пустой список, ещё не загруженные данные и ошибку. Сохранение заметки в нашей сцене действует только до сброса или смены примера.
<wa-tab-group>
<wa-tab panel="overview">Клиент</wa-tab>
<wa-tab panel="notes">Заметка</wa-tab>
<wa-tab-panel name="overview">Сведения о клиенте</wa-tab-panel>
<wa-tab-panel name="notes">
<wa-textarea label="Внутренняя заметка"></wa-textarea>
</wa-tab-panel>
</wa-tab-group>
Документация: группа вкладок и события.
Пример 5. Дерево документов с выбором листа
Дерево передаёт иерархию: документы относятся к проектам или команде. Родительские узлы в нашей сцене раскрывают группы, а выбор листа меняет заголовок и описание справа. Попробуйте перейти стрелками и выбрать другой документ с клавиатуры. Это важный способ работы, когда элементов много или мышь неудобна.
Идентификатор документа хранится отдельно от его подписи. Благодаря этому текст можно переименовать, не меняя логику выбора. В реальном сервисе такой ID передаётся в API, а сервер проверяет право читать объект. Наличие видимого узла в дереве само по себе не является разрешением доступа.
Большую файловую структуру не нужно целиком загружать при открытии страницы. Можно раскрывать ветви по мере необходимости, показывая загрузку и ошибку рядом с соответствующей папкой. Но это уже отдельная задача приложения: наша мастерская содержит небольшой локальный набор и помогает сначала разобраться с выбором, раскрытием и обратной связью.
tree.addEventListener('wa-selection-change', event => {
const selected = event.detail.selection[0];
const documentId = selected?.dataset.doc;
if (!documentId) return;
title.textContent = documents[documentId].title;
});
Документация: режимы выбора дерева.
Пример 6. Калькулятор команды и ясная цена
Слайдер задаёт количество участников, а переключатель меняет период оплаты. Сумма за год считается с учебной скидкой и подписывается именно как годовой платёж. Ниже отдельно показан месячный эквивалент. Это избавляет от распространённой путаницы, когда крупное число относится к месяцу, а списывается сразу за год.
Исходная цена в примере — 500 рублей за участника в месяц. Для пяти участников годовая сумма со скидкой 20 процентов равна 24 000 рублей. Значение можно менять стрелками клавиатуры. При переносе калькулятора в продукт показывайте также границы, шаг, единицы и условия скидки — одних красивых цифр недостаточно.
Клиентский расчёт нужен для обратной связи, но окончательную цену должен определять сервер. Не принимайте присланную из браузера сумму как достоверную стоимость заказа. В мастерской нет оплаты и договора: это пример оформления выбора и пересчёта, который можно адаптировать под свою модель тарифа.
const monthly = seats * 500 * (annual ? 0.8 : 1);
const periodTotal = monthly * (annual ? 12 : 1);
const formatter = new Intl.NumberFormat('ru-RU', {
style: 'currency', currency: 'RUB', maximumFractionDigits: 0
});
price.textContent = formatter.format(periodTotal);
Пример 7. Оценка, комментарий и квитанция
Рейтинг удобен для быстрого ответа после обслуживания, но сам по себе плохо объясняет причину оценки. Поэтому рядом находится комментарий. В нашей сцене после нажатия формируется локальная квитанция с фактическими значениями формы. Она показывает разработчику структуру результата и даёт человеку явное подтверждение действия.
Если оценка обязательна, продумайте начальное состояние отдельно. Заранее выбранные четыре звезды подходят демонстрации управления, но в настоящем исследовании могут влиять на ответы. Также решите, может ли человек изменить оценку позже и нужно ли подтверждать отзыв перед публикацией. Это продуктовые решения, которые библиотека не принимает.
В рабочей версии квитанция должна соответствовать успешному ответу backend. При сетевой ошибке текст комментария лучше сохранить на экране. Не очищайте всю форму после неудачной попытки: повторный ввод особенно раздражает на телефоне. Пользовательский текст выводите как текст, а не как произвольную HTML-разметку.
Документация: рейтинг и управление значением.
Пример 8. Разделяемая рабочая область
В редакторе или операторской панели полезно дать человеку управлять шириной списка и области содержимого. Split panel предоставляет разделитель, а наша сцена добавляет понятные пресеты 30 процентов и поровну. Кнопки помогают быстро вернуть удобное соотношение и служат альтернативой точному перетаскиванию.
На узком экране две колонки становятся слишком тесными. Поэтому пример переключает orientation в vertical: список располагается над подробностями. Это реальное изменение компоновки, а не простое уменьшение шрифта. Текущая позиция разделителя выводится рядом, чтобы результат действия оставался понятным.
В рабочем приложении можно сохранять предпочтение пользователя, но нужно учитывать разные размеры экранов. Удобные 25 процентов на большом мониторе не означают пригодные 25 процентов на телефоне. Задавайте минимальные области, проверяйте длинные заголовки и оставляйте возможность сбросить случайно неудобное положение.
const media = matchMedia('(max-width: 540px)');
function updateOrientation() {
panel.orientation = media.matches ? 'vertical' : 'horizontal';
}
updateOrientation();
media.addEventListener('change', updateOrientation);
// При удалении экрана:
// media.removeEventListener('change', updateOrientation);
Документация: ориентация и позиция разделителя.
Пример 9. Чек-лист и честный прогресс
Полоса прогресса полезна только тогда, когда понятно, что она измеряет. В нашей сцене процент вычисляется из четырёх отмеченных пунктов. Если снять галочку, он уменьшается. Это не таймер, изображающий неизвестную серверную работу, и не обещание автоматической проверки доступа или данных.
Такой экран можно использовать для первичной настройки кабинета или подготовки проекта. Рядом с каждым пунктом желательно дать конкретный путь к действию. Если система умеет самостоятельно проверить условие, состояние должно приходить из проверенного результата. Если пункт подтверждает человек, интерфейс должен честно показывать именно это.
Раскрываемое пояснение помогает не перегружать основной экран длинным текстом. Важное действие остаётся заметным, а подробности доступны по запросу. После переноса в рабочую систему продумайте частичное выполнение, право сбросить пункт и поведение при ошибке сохранения. Галочка в браузере и выполненная бизнес-процедура — разные уровни состояния.
const completed = items.filter(item => item.checked).length;
progress.value = completed / items.length * 100;
status.textContent = `Готово ${completed} из ${items.length}`;
Оформление: токены, CSS Parts и согласованный акцент
Вместо отдельных цветов на каждой кнопке задайте несколько общих решений: акцент, поверхность, расстояния и радиусы. Токены библиотеки позволяют менять группу компонентов согласованно. В мастерской переключатель акцента меняет цвет основного действия и фокуса, сохраняя белую надпись и читаемость выбранных вариантов.
Не все изменения должны быть глобальными. Например, кнопке в узком диалоге может понадобиться перенос длинной подписи. Для этого используется открытая CSS-часть. Но перед настройкой сверяйте название part в документации закреплённой версии: внутренний класс и публичная часть — не одно и то же.
Проверяйте оформление в реальных состояниях: обычном, наведённом, выбранном, недоступном и с клавиатурным фокусом. Красивый акцент на большой карточке может стать плохо различимым в маленькой подписи. Также полезно смотреть весь экран, чтобы элементы библиотеки сочетались с таблицами, заголовками и внешней сеткой сайта.
:root {
--wa-color-brand-fill-loud: #12695d;
--wa-color-brand-on-loud: #ffffff;
--wa-color-focus: #12695d;
}
wa-button::part(base) { white-space: normal; }
Документация: дизайн-токены.
События, жизненный цикл и сохранение состояния
У разных компонентов события отличаются: обычные input и change соседствуют с wa-selection-change или wa-tab-show. Не подключайте один случайный обработчик ко всему экрану, надеясь получить одинаковые данные. Сверьте имя события, его detail и момент возникновения, а затем запишите небольшой проверяемый обработчик.
При удалении сцены нужно завершить работу, связанную с внешним окружением. В нашей рабочей области снимается слушатель matchMedia. Диалоги и панели закрываются при смене примера. Для запросов, таймеров и подписок в реальном приложении потребуется такое же явное завершение, иначе старый экран сможет обновить уже неактуальное состояние.
Возврат браузером назад тоже требует внимания. Страница может восстановиться из кеша истории вместе со своим состоянием. Поэтому мастерская не уничтожает обработчики при pagehide, если страница сохраняется браузером. Такой нюанс легко пропустить, если проверять только первую загрузку и обычное обновление.
Как подключить API и не потерять пользовательские данные
Следующий шаг после локальной квитанции — запрос к своему backend. Сначала определите контракт: какие поля принимаются, какие обязательны, какие значения разрешены и что возвращается при ошибке. Затем отдельно проверьте права пользователя. Поле роли, ID документа или сумма из клиента не должны автоматически определять полномочия и стоимость.
На время запроса блокируйте повторное сохранение, но сохраняйте введённое содержимое. Если сервер вернул ошибки полей, покажите их возле соответствующих контролов и дайте общий понятный результат. Если изменился объект, который успел отредактировать другой сотрудник, понадобится стратегия конфликта версий. Простая надпись «Ошибка» не объясняет человеку, что делать дальше.
Для PHP-проекта можно совместить эту мастерскую с серверной проверкой данных, а для частичного обновления HTML — с материалом о htmx. Но не отправляйте учебные формы на произвольный публичный URL: сначала создайте и проверьте собственный маршрут с нужными ограничениями.
Доступность: клавиатура, подписи и управление фокусом
Наличие готового компонента уменьшает объём ручной работы, но не гарантирует доступность всего приложения. Поле всё равно нуждается в понятной подписи, диалог — в ясном заголовке, действие — в осмысленном названии. Информация не должна передаваться только цветом. Сообщение о сохранении важно связать с фактическим результатом.
Пройдите сценарий без мыши: Tab до нужного элемента, стрелки внутри составного компонента, Enter для действия и Escape для закрытия. Проверьте, куда возвращается фокус. Если после удаления карточки фокус исчезает или перескакивает в начало документа, человеку приходится заново искать своё место.
Мы проверяем такие пути в браузере, но отдельно не заявляем полный аудит со скринридерами. Для продукта нужны проверки на его реальном наборе устройств и вспомогательных средств. Поддержка уменьшенного движения тоже важна: в мастерской CSS сокращает переходы при соответствующей настройке системы.
Документация: подход библиотеки к доступности.
Мобильный интерфейс и встраивание в статью
Мобильная пригодность определяется не только отсутствием горизонтальной полосы прокрутки. Нужно, чтобы подписи помещались, кнопки оставались достаточно крупными, а длинный текст не вытеснял действия за пределы доступной области. В нашей мастерской формы выстраиваются в колонку, карточки перестраиваются, а разделяемая область меняет ориентацию.
Панель фильтров и диалог ограничены шириной окна. При встраивании через iframe этим окном становится область мастерской, а не весь экран сайта. Поэтому рядом со встроенным примером есть открытие на весь экран. Для длинной формы или подробного редактора такой режим удобнее, чем попытка уместить всё в небольшой блок статьи.
Проверяйте также экранную клавиатуру телефона, поворот устройства и увеличение текста. Эмуляция узкой ширины помогает обнаружить ошибки сетки и переносов, но не заменяет все физические особенности устройства. Перед применением в рабочем сервисе стоит пройти основные действия на настоящем телефоне.
Windows: как повторить мастерскую у себя
Скачайте ZIP и распакуйте его в отдельную папку. Установите Node.js 24 с официального сайта, затем откройте PowerShell в корне webawesome-project. Выполните установку по lock-файлу, сборку, тесты и запуск. Локальный сервер слушает только loopback, поэтому это удобный стенд для своего компьютера.
Откройте http://127.0.0.1:8144/ и начните с формы профиля. Проверьте пустое обязательное поле, затем успешную квитанцию. После этого откройте фильтры, выберите два условия и скачайте пример. Так вы проверите не только наличие страницы, но и основные рабочие пути.
Если порт уже занят, выберите другой через переменную PORT. Не завершайте неизвестный процесс лишь ради освобождения номера. Остановить наш сервер можно Ctrl+C в его терминале. Открытие HTML двойным щелчком не является равноценной проверкой: загрузка модулей через file:// может ограничиваться браузером.
node --version
npm ci
npm run build
npm test
npm start
# Другой порт в текущем PowerShell:
# $env:PORT = '8154'
# npm start
Linux: запуск, PHP-сервер и состав production-файлов
В Linux используется тот же проект и тот же lock-файл. После установки Node.js 24 команды npm ci, npm run build и npm test повторяют сборку. Для разработки можно запустить приложенный Node-сервер или, если PHP уже установлен, его встроенный сервер с корнем public.
PHP в данном случае только отдаёт готовые HTML, CSS и JavaScript. Он не обрабатывает наши формы и не хранит данные. Это полезное разделение: интерфейс можно разместить рядом с PHP-приложением, но подключение backend нужно сделать явно. Наличие файла index.html не создаёт серверную валидацию автоматически.
После сборки постоянный процесс Node для мастерской не требуется. Production-веб-сервер может раздавать содержимое public как статику. Не публикуйте весь каталог проекта в качестве document root: тесты и конфигурация сборки нужны разработчику, а посетителю нужны только ресурсы страницы и разрешённые скачиваемые материалы.
npm ci
npm run build
npm test
PORT=8144 npm start
# Альтернатива, если PHP установлен:
# php -S 127.0.0.1:8144 -t public
Linux VPS: HTTPS, размещение, обновление и откат
Для сервера удобна схема с каталогами релизов. Сначала передайте архив, распакуйте новую версию отдельно, установите зависимости и соберите public. Только после проверок переключайте current на готовую версию. Предыдущую папку сохраняйте до завершения приёмки, чтобы откат не требовал срочной повторной сборки.
В архиве есть пример Caddyfile для собственного домена. Корень указывает на public, включено сжатие и корректная раздача статических ресурсов. Настройте DNS, доступность нужных портов и сохраните остальные сайты в существующей конфигурации. Подробности HTTPS разобраны в статье о Caddy.
После размещения проверьте HTTP-ответ страницы и JavaScript MIME у vendor/webawesome.js. Затем повторите форму, диалог и скачивание прямо на домене. Ошибка MIME, недоступный ресурс или неверный путь могут проявиться только на хостинге. Инструкция для VPS приложена полностью, но отдельный внешний сервер и выпуск сертификата не считаются уже выполненными проверками этого материала.
ui.example.com {
root * /srv/webawesome/current/public
encode zstd gzip
header X-Content-Type-Options nosniff
file_server
}
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -I https://ui.example.com/
curl -I https://ui.example.com/vendor/webawesome.js
Что проверять при изменении и обновлении библиотеки
Проверки должны отражать поведение, которое важно человеку. Для фильтра это применение двух условий и отмена черновика. Для тарифа — правильный период суммы. Для дерева — пустой выбор и выбор листа. Для разделителя — смена ориентации и удаление слушателя после закрытия экрана. Именно такие случаи включены в тесты прикладной логики.
Отдельно нужен настоящий браузер: DOM-модель не заменяет реализацию пользовательских элементов, FormData и фокус диалога. В браузере проверяются компоненты, обязательность полей, клавиатура, переключение сцен, экспорт и мобильная компоновка. При обновлении библиотеки сначала прогоните эти пути, а затем переносите новую сборку на сайт.
Оценивайте также размер и загрузку. Мастерская импортирует используемые компоненты явно и собирает зависимости локально. В большом приложении можно разбить редкие экраны на отдельные модули, но это добавляет состояние ожидания и ошибки загрузки. Ускорение полезно, если после него интерфейс остаётся предсказуемым.
Исходники, лицензии и следующий шаг
В архиве находятся девять сценариев, общий интерфейс, сборщик, локальный сервер, тесты, лицензии и инструкция для Windows, Linux и VPS. Кнопка отдельного примера сохраняет HTML с точным обработчиком выбранной сцены. Разместите его в public рядом с index.html: он использует локальные vendor и style.css. Это исходный пример, а не выгрузка введённых вами личных значений.
Собственный код распространяется по MIT. Web Awesome Core и Bootstrap также имеют MIT-лицензии; встроенные SVG-иконки Font Awesome Free сопровождаются условиями CC BY 4.0. Уведомления находятся в проекте и сохраняются при сборке. Использованные компоненты не требуют Pro-подписки.
Для практического внедрения выберите один повторяющийся экран своего сервиса. Например, перенесите профиль и фильтры, согласуйте подписи, добавьте настоящий API и проверьте ошибочный ответ. Затем развивайте библиотеку собственных экранов из уже проверенных элементов. Такой путь помогает получить удобный продукт, в котором компоненты поддерживают задачу пользователя, а не отвлекают от неё.
Документация: лицензия Web Awesome Core.


