Рад поделиться, что мы опубликовали первый стабильный релиз четвертой мажорной версии Taiga UI — нашей огромной библиотеки компонентов для Angular. Улучшений в нем так много, что одной статьи едва ли хватит. Расскажу про самые аппетитные из них.
Мажорный релиз — новый шаг нашей истории
Мы в команде всегда относились к мажорным релизам как к важному и ответственному шагу: не злоупотребляли их частотой, а длительность подготовки измерялась месяцами или даже сезонами.
В декабре 2020 года состоялся наш второй мажорный релиз — с него началась open-source-история нашего проекта. Третий мажорный релиз был анонсирован лишь в конце лета 2022 года. К началу разработки четвертой версии Тайги мы приступили в декабре 2023 года, а анонс первого стабильного релиза и вовсе оглашаем лишь сейчас.
Разумеется, в перерывах между мажорными релизами мы не сидим без дела, а продолжаем релизиться почти каждую неделю. Например, у второй мажорки было аж 99 минорных релизов. Но самое интересное происходит всегда именно с наступлением breaking changes…
Поднятие минимальной версии Angular
В своих прошлых статьях я упоминал о том, что авторы библиотек под Angular сталкиваются с весьма серьезным ограничением — необходимостью обеспечивать совместимость своих библиотек с приложениями, написанными на старых версиях Angular.
Да-да, как бы мы ни хотели, как бы много у нас ресурсов ни было, мы не можем сразу начать использовать самую свежую версию Angular для публикации своих библиотек. Стоит нам обновиться до самой последней версии, и наши пользователи не смогут пользоваться нашими продуктами, пока сами не обновятся до такой же версии или выше. Так как нашими библиотеками пользуются сотни продуктовых команд, это непозволительная роскошь.
Поэтому всю третью мажорную версию мы сидели на Angular 12. Нам было несладко: команда фреймворка за четыре года убежала далеко вперед. Но, к счастью, мы наконец-то обновляемся до 16-й версии фреймворка.
Что это значит для вас:
Если вы уже используете в своих приложениях современный Angular, вам не стоит беспокоиться — все продолжит работать. Если же вы используете что-то постарее 16-й версии, пришло время
уволиться с текущего места работымотивировать свою команду выделить время на обновление Angular перед тем, как обновляться до свежей Тайги.Вы сможете наконец-то забыть про модули! В новом релизе мы переписали все наши директивы и компоненты на standalone, это должно значительно улучшить тришейкинг. Более того, мы поменяли правила их наименования и убрали ненужные постфиксы. Читаете документацию про
TuiButton
? Значит, и в импорты своего компонента добавляйте сущностьTuiButton
(а неTuiButtonModule
илиTuiButtonComponent
). Код проще и красивее!
Что это дает нам:
Стали доступны хост-директивы, которые открывают для нас новые пространства для декомпозиции и упрощения кода. Благодаря им отпадает необходимость в дополнительной вложенности для применения директив, что превращает многие компоненты в директивы. Это не только хорошо для вашей кастомизации, но и позволит нам в будущем вынести стили в отдельный пакет, описать их публичный API через атрибуты
data-*
и использовать внешний вид многих простых компонентов даже без Angular.Кто знает, может, в будущем вы увидите тайговые компоненты под React или вовсе под проекты, написанные на ванильном JavaScript? Давайте вместе помечтаем об этом, говорят, это делать не вредно :D
Мы впервые потрогали сигналы и с их помощью упростили часть кода. В полной мере ощутить всю их мощь сможем лишь с переходом на 17-й Angular, когда нам станут доступны сигнальные инпуты, а еще сигнальные версии двухстороннего связывания и инструменты для работы с элементами шаблона. Но уже первое знакомство с сигналами нас сильно впечатлило!
Поднятие браузерной поддержки
Каждый мажорный релиз мы сопровождаем пересмотром минимальных версий поддерживаемых браузеров. Это сопровождается тем, что мы выкидываем из кодовой базы множество костылей, существовавших только ради древних браузеров. Для вас это означает, что библиотеки Taiga UI становятся легче, а также стабильнее (ведь мы полностью переносим часть функций на нативные рельсы браузеров).
В текущем мажорном релизе мы значительно подняли планку по многим браузерам. Наконец-то без полифилов и без каких-либо фолбэков нам стали доступны такие браузерные API, как ResizeObserver, Clipboard, VisualViewport, а также события указателя и крайне полезное для всех наших замаскированных текстовых полей beforeinput-событие.
Актуальный список поддерживаемых браузеров теперь публикуется в качестве библиотеки — @taiga-ui/browserslist-config.
Пакет @taiga-ui/legacy
С четвертым мажорным релизом мы стали публиковать пакет @taiga-ui/legacy, который станет промежуточным состоянием для многих устаревших компонентов перед их полноценным удалением. Все сущности, которые вы найдете внутри пакета в четвертом мажорном релизе, будут удалены в пятом. А во время подготовки к новому мажорному релизу пакет вновь наполнится чем-то устаревшим.
Мотивация создания пакета — упрощение миграции на новую мажорку. В большинстве случаев участники пакета — это компоненты, которые уже имеют современный аналог из стабильных пакетов, но их процесс миграции слишком сложно покрыть автоматическими миграциями, и требуются ручные усилия.
Мы посчитали, что вам будет легче вначале мигрировать все обязательные сущности и только потом, уже в комфортном для себя темпе, избавиться и от всех оставшихся сущностей из @taiga-ui/legacy
-пакета. Но всегда держите в уме, что такие компоненты уже не получают поддержки, — старайтесь как можно быстрее пересесть на современные аналоги.
Эксперименты переехали в стабильные пакеты
Пользователи наших пакетов могли заметить в документации раздел под названием “Experimental”. Раздел пополнялся описанием все большего количества директив и компонентов из некоего пакета @taiga-ui/experimental
.
Такой подход наша команда переняла от команды Angular. Например, она публикует пакет @angular/material-experimental
, в корневом README которого содержится фраза:
Этот пакет содержит прототипы и эксперименты. Ничто в этом пакете не считается стабильным или готовым к использованию в продуктовых приложениях. Хотя пакет выпускается вместе с остальными стабильными пакетами Angular Material, ломающие изменения могут произойти в любом из релизов.
Наша стратегия следует таким же принципам. Новый пакет @taiga-ui/experimental
позволяет пользователям уже на ранних этапах увидеть, какая траектория намечается у следующего мажорного релиза. Пользователи при желании даже могут начать использовать этот пакет в своих приложениях и оставлять нам обратную связь. Главное, чтобы такие смельчаки всегда помнили, что обновление экспериментального пакета нужно делать осторожно, ведь в любой момент публичный API его содержимого может незначительно поменяться.
Большая часть содержимого @taiga-ui/experimental
в ближайшем мажорном релизе переезжает в стабильные пакеты. Сам экспериментальный пакет при этом продолжает существовать пустым до момента, пока мы не начнем его пополнять в рамках подготовки к новому мажорному релизу.
Многие описанные в статье новинки были когда-то частью такого экспериментального пакета, а теперь они переехали в разные стабильные тайговые библиотеки.
Переходим к детальному разбору каждой новинки!
Radio и Checkbox
Как все было раньше — на примере чекбоксов:
Хотим получить просто маленький квадратик, при клике по которому у него внутри появляется галочка?
Импортируем TuiCheckboxModule
и используем следующую разметку:
<tui-checkbox [(ngModel)]="value" />
Захотели получить такой же чекбокс, но уже с текстом по соседству, при клике на который чекбокс тоже переходит в выбранное состояние?
Вновь импортируем новый модуль TuiCheckboxLabeledModule
и используем следующую разметку:
<tui-checkbox-labeled [(ngModel)]="value">
Click on the text too
</tui-checkbox-labeled>
Еще пример.
По факту это лишь дополненная версия предыдущего компонента CheckboxLabeled
, но теперь он еще задекорирован дополнительной границей и клик/наведение теперь работает на всей площади блока.
Вновь вспоминаем название очередного модуля — TuiCheckboxBlockModule
, а разметка такого компонента теперь выглядит так:
<tui-checkbox-block [(ngModel)]="value">
An option
</tui-checkbox-block>
Чтобы вы в полной мере прочувствовали всю боль, напомню, что такая же ситуация идентично повторялась для радиокнопок. Существовали аналогичные TuiRadioModule, TuiRadioLabeledModule и TuiRadioBlockModule все с той же логикой, что я и рассказал выше.
А теперь, когда я в полной мере раскрыл всю ситуацию прошлого, оцените красоту обновленной версии этих компонентов.
Для создания самых базовых чекбоксов и радиокнопок теперь импортируем TuiCheckbox
и TuiRadio
и используем следующую разметку:
<input
tuiCheckbox
type="checkbox"
[ngModel]="value"
/>
<input
tuiRadio
type="radio"
[(ngModel)]="value"
/>
Хотим им добавить кликабельные подписи, при клике на которые будет срабатывать взаимодействие? Тут новый стиль вам должен очень понравиться, ведь он максимально близок к нативному. Импортируем TuiLabel, а дальше просто оборачиваем инпуты выше тегом label
(работает одинаково и для чекбоксов, и для радиокнопок):
<label tuiLabel>
<input
tuiCheckbox
type="checkbox"
[(ngModel)]="value"
/>
Label text
</label>
Хотим повторить поведение прошлых TuiCheckboxBlockModule
/ TuiRadioBlockModule
? Теперь и для этого случая у них есть одно общее решение! Импортируем TuiBlock
, дальше просто подменяем директиву на теге label
:
<label tuiBlock>
<input
tuiCheckbox
type="checkbox"
[ngModel]="value"
/>
Label text
</label>
Все примеры нового API актуальны и для новой радиокнопки.
Более того, директивы Label
и Block
работают еще и с новым Switch-компонентом.
<label tuiBlock>
<input
tuiSwitch
type="checkbox"
[ngModel]="value"
/>
Label text
</label>
Новые версии Checkbox
, Radio
и Switch
получили однородный публичный API, который легко запоминается, так как он максимально близок к нативному синтаксису аналогичных браузерных компонентов.
SwipeActions
В стабильный пакет @taiga-ui/addon-mobile
перебрался экспериментальный компонент SwipeActions. Его идея проста и понятна многим, так как она реализована практически во всех популярных почтовых сервисах (например, Gmail). Хотите на мобильных девайсах по горизонтальному свайпу давать пользователям набор дополнительных действий? Тогда новый компонент возьмет большую часть забот на себя, а вам лишь останется декларативно через шаблон описать содержимое таких действий.
Технически потребуется любой контент обернуть в <tui-swipe-actions />
, а рядом положить набор кнопок-иконок, которые покажутся при осуществлении свайпа:
<tui-swipe-actions>
<div>
Any content you like
</div>
<button
appearance="destructive"
iconStart="@tui.trash"
size="s"
tuiIconButton
tuiSwipeAction
></button>
</tui-swipe-actions>
Sensitive
Наш основной @taiga-ui/kit
пополнился любопытной директивой — Sensitive. Она позволяет визуально спрятать любую часть контента от пользователя. Например, в приложениях Т-Банка такая фича активно применяется, чтобы пользователь мог спрятать свои чувствительные данные — значение баланса или банковского счета, когда делает запись экрана или показывает что-то лично своим знакомым.
Главная прелесть этой директивы, что она совместима с любым нативным тегом или кастомным компонентом. Единственное ограничение, что у вас не должен быть занят псевдоэлемент :after
у скрываемого контента. И это ограничение при необходимости легко обходится дополнительной вложенностью.
Skeleton
Ближайший родственник предыдущей новинки — директива для построения скелетонов.
Скелетон в вебе — временная заглушка, которая занимает место еще не загруженного контента страницы и отображает его примерный макет до момента окончания его загрузки. Визуально скелетоны — обычно что-то серое, имеющее небольшую пульсирующую анимацию, чтобы передать состояние загрузки.
Новая директива Skeleton может вешаться на любой нативный тег или любой ангуляр-компонент — любых форм и любых размеров. А дальше через магию css-свойства filter директива превращает любой контент в скелетоны.
Segmented
Новый компонент Segmented — популярный прием использования кнопок в навигациях приложений. Особенно когда пытаются приблизить внешний вид приложения к нативному мобильному виду.
Fade
Многоточие в конце — популярный способ отображать переполнение текста. Если такой вариант наскучил, есть новый — компонент Fade, который наконец-то переехал в стабильный пакет @taiga-ui/kit
.
DropdownMobile
Хоть этот компонент и был продублирован в третьей мажорной ветке, его создание произошло в момент активной работы над свежим мажорным релизом. Поэтому было бы преступлением не упомянуть про него в этой статье.
Наша команда разработала новую версию выпадашек для мобильных устройств. Часто бывает, что классическим десктопным выпадашкам слишком тесно на маленьком мобильном экране. Тут на помощь и придет новая директива TuiDropdownMobile из пакета @taiga‑ui/addon‑mobile
.
Нужно навесить директиву tuiDropdownMobile
на уже привычные вам компоненты Select, MultiSelect или ComboBox, а дальше директива все сделает за вас: в начале взаимодействия с этими компонентами с десктопа будет открывать уже привычный вам вариант выпадающего списка, а при попытке сделать это с мобильного устройства откроется тот, что продемонстрирован на иллюстрации выше.
Семейство компонентов @taiga-ui/layout
Не всегда компоненты обязаны быть «набиты» огромным количеством JavaScript-кода. Иногда для счастливой жизни веб-разработчика не хватает гусиной фермы набора готовых шаблонов, чтобы меньше заниматься версткой. И в последнем релизе наш пакет @taiga-ui/layout
пополнился полезными компонентами и директивами под эту задачу.
Новые компоненты CardMedium и CardLarge помогут верстать подобные карточки с минимальными усилиями. В статье я прикрепил лишь один вид из множества возможных вариаций. В документации вы найдете гораздо больше интересных примеров.
Новый компонент Cell найдет себе отличное применение в длинных списках с большим количеством текстового контента.
Новый компонент этого пакета BlockDetails в паре с уже ранее существующим BlockStatus поможет создавать отличные страницы состояний в вашем приложении.
Icon
До текущего мажорного релиза наш подход с иконками базировался на использовании тега <svg /> в паре с тегом <use />. Подход вполне рабочий, но переусложенный по своей кодовой базе: сущностей и скриптов для препроцессинга иконок перед их использованием существовало такое огромное количество, что описания принципа их работы хватило бы на отдельную статью.
В новом мажорном релизе в пакете @taiga-ui/core
появился новый компонент Icon, который и стал основным способом работы с иконками во всех остальных тайговых компонентах. Новый способ отображает иконки через CSS-маску, что открывает новые горизонты:
Возможность хранить иконки на CDN и отображать их без манипуляций с DOM и санитайзера.
Упрощенный способ масштабирования иконок. Достаточно менять размеры хоста компонента — иконка масштабируется автоматически, а свойство vector‑effect="non‑scaling‑stroke" позволит реализовать это масштабирование без потери деталей и ненужного уменьшения/увеличения толщины линий.
Браузер автоматически реализует кэширование иконок.
Обновленный InputPhoneInternational
Наш InputPhoneInternational наконец-то перестал полагаться на набор захардкорженных констант, которые мы никогда не успевали обновлять!
Больше мы не храним у себя информацию о сотнях паттернов телефонных номеров разных стран. Теперь за нас это делает Google. У компании есть библиотека libphonenumber, которая хранит паттерны телефонных номеров всех стран мира, и они всегда поддерживаются в актуальном состоянии!
Еще даже до начала работы над четвертым мажорным релизом Тайги мы заранее реализовали библиотеку @maskito/phone. Она использует порт гугловской библиотеки под JS-формат и всю мощь Maskito, чтобы в пару строчек кода создавать замаскированное текстовое поле для телефонного номера любой страны мира. А теперь мы внедрили эту библиотеку в тайговый InputPhoneInternational
.
Но и это еще не все! Все это время наш публичный вариант компонента использовал флаги стран в не очень хорошем растровом формате изображения. Но теперь наш пайп tuiFlag будет на выходе отдавать не *.png
, а красивые и качественные векторные изображения!
Textfield и новые инпуты
И напоследок я оставил самый масштабный рефакторинг кода, который даже не закончится на текущем мажорном релизе, а будет продолжаться в последующих публикациях.
Мы переработали компонент PrimitiveTextfield. На нем базируются все остальные разновидности текстовых полей. Обновленная версия этого компонента получила название Textfield.
Главная особенность нового компонента в том, что стиль его использования сильно изменился. Textfield
задается и кастомизируется в весьма декларативном стиле через шаблоны, а не через «миллионы» инпут-пропертей, как это было ранее.
Приведу самый базовый пример:
<tui-textfield
iconStart="@tui.search"
iconEnd="@tui.settings"
>
<label tuiLabel>I am a label</label>
<input
placeholder="I am placeholder"
tuiTextfield
[(ngModel)]="value"
/>
<tui-icon icon="@tui.bell" />
<tui-icon tuiTooltip="I am a hint" />
</tui-textfield>
Вот такое текстовое поле получится:
После создания этого компонента мы переместили все остальные виды текстовых полей в @taiga-ui/legacy
. А после поставили цель создать их новые альтернативы, но уже в похожем стиле, что и задает их базовый компонент Textfield
. Часть компонентов уже переписана под новый стиль (например, InputCard), а другая часть будет завершена в следующих релизах.
В заключение
Четвертый мажорный релиз уже доступен к скачиванию. Все перечисленные новинки — далеко не полный список улучшений, подробный читайте в changelog релиза.
Мы приложили максимум усилий, чтобы упростить вам процесс обновления. Написали кучу схематиков, которые автоматически пройдутся по всему вашему проекту и устранят большую часть ломающих изменений.
Если вы используете Angular CLI, то, чтобы запустить скрипты с миграциями, воспользуйтесь консольной командой:
ng update @taiga-ui/cdk
А если же ваш проект базируется на Nx CLI, то команда запуска:
nx migrate @taiga-ui/cdk
Если вы случайно забрели в эту статью и теперь хотите попробовать Тайгу в своем проекте, то и на этот случай мы подготовили вам команду, которая упростит старт:
ng add taiga-ui
Если столкнетесь с какими-либо проблемами или багами в процессе обновления, не стесняйтесь заводить issue или задать вопрос в нашем телеграм-сообществе. Команда Тайги с нетерпением ждет вашей обратной связи!
А также напоминаем, что самый простой способ сказать нам спасибо — поддержать нас звездочкой на Гитхабе.