Привет! Меня зовут Вадим Казаченко, я лид фронта дизайн-системы ВТБ. Год назад устроился в банк и получил командную задачу — построить единую библиотеку компонентов, настолько универсальную, чтобы ее можно было использовать в любом продукте дизайн-системы банка, и при этом она не должна становиться «узким горлышком», как это обычно происходит с UI-китами в крупных компаниях. Дело в том, что в ВТБ существует множество дизайн-систем, над которыми работают десятки дизайнеров. Непростая задача требовала проработки архитектуры дизайн-системы и сильно зависела от выбора решения для стайлинга. В этой статье подробно расскажу, от чего мы отталкивались и на чем остановили свой выбор. Первую версию CSS мы получили в далеком 1996 году, и с тех пор концептуально ничего не менялось: схема Selector { Property: Value } и полная статичность. Плюсом было только то, что грузятся стили из файла параллельно с загрузкой JS-кода. Если вы, конечно, не произвели весь стайлинг внутри HTML-страницы, что замедлило бы ее загрузку. Работать со стилями стало приятнее с появлением препроцессоров. Некоторые из них добавляли улучшенный синтаксис, переменные и функции для генерации CSS, другие же, как postCSS, дали возможность совершать манипуляции со стилями. Популярные расширения postCSS позволили автоматически добавлять префиксы для одинакового отображения стилей в браузерах, уменьшали размерность файлов для загрузки пользователями или же помогали проверять разработчикам код на ошибки линтерами. Кроме этого, пришлось еще решать существенную проблему: бесконечное число хаотично названных классов периодически создавали конфликты, что крайне мешало в работе над масштабным проектом. Решением стало использование CSS-модулей в сочетании с методологией нейминга классов БЭМ (Блок, Элемент, Модификатор). Пример использования классов в БЭМ: БЭМ описала правила к наименованию компонентов, его составных частей и модификаций. CSS-модули позволили безболезненно распиливать стили на разные файлы и ограничивать локальной областью, где к их классам добавился уникальный ключ, исключающий повторы в названиях.  В совокупности с препроцессорами эти решения так хорошо зашли, что до сих пор поставляются из коробки в самых современных фреймворках. Итак, при использовании этого подхода получаем следующее: Плюсы Компоненты стилизуются модульно. Нет наложения нейминга классов. Статичный CSS загружается параллельно с JS. Нет проблем с SSR. Минусы Сложно заводить и поддерживать токены для реализации тем. Отсутствие типизации и подсказок без настройки IDE. Чтобы соединить стили с компонентами, нужно маппить классы с пропсами. Давайте забьем на CSS и будем генерировать стили прямо из JS. Это легло в основу большинства библиотек, реализующих этот подход. Здесь не нужно прописывать какие-либо классы и разбираться, как компонентам их переключать. Под капот уходят все вопросы добавления префиксов, ключей к названиям и минификации. Все стало крайне легко: берется функция styled, которая оборачивает HTML-тег, который нужно стилизовать. Стили добавляют через шаблонные строки, и в них же можно получать прямой доступ как к пропсам компонента, так и к общей теме, которую одним движением легко переключить со светлой на темную и так далее. Итого, при использовании этого подхода получаем следующее: Плюсы: Не нужно думать о соединении стилей с пропсами. Темы переключаются на лету. SSR поддерживается, но есть нюансы. Минусы: Отсутствие типизации и подсказок. Рендер стилей происходит только после загрузки JS. Бесконечная генерация классов с хаотичным неймингом. А что лучше, чем CSS-in-JS? Логичным продолжением развития работы с CSS-in-JS стал переход к CSS-in-TS и его реализация в библиотеке stitches.dev с отличной документацией и широкими возможностями. Какие еще важные для нас преимущества можно отметить? Первый плюс — базовый стайлинг. Обертка styled практически такая же, как в styled-components, только стилизация происходит внутри объекта, а не строки. Для каждого CSS-свойства заданы типы, что позволяет без особого труда выставить стили с подсказками редактора кода и заняться более важными делами. Второй плюс. Динамичность в этой библиотеке реализована с помощью вариантов: пропсы, которые передаются в компонент, переключают статичные объекты стилей. Помните, я упоминал БЭМ ранее в статье? Это по сути и есть его реализация, но без лишних движений! Плюс третий. Способ реализации stitches.dev исключает возможность использования функций и при этом повышает читаемость кода. В своих же бенчмарках (https://stitches.dev/docs/benchmarks) авторы сравнивают подход вариантов против полностью генерируемых стилей. Это не особо показывает реальную производительность, зато подсвечивает, что в других библиотеках достаточно легко можно допустить ошибку и потерять эффективность.  Если библиотека позволяет стилизовать компоненты, это не значит, что ее будет удобно использовать в UI-ките. В вопросах типового стайлинга stitches.dev в целом понятная и удобная система, но давайте рассмотрим ее в рамках работы UI-кита — это непосредственно относится к нашей задаче. Stitches со стартового гайда предлагает создать файл конфигурации, в котором можно определить тему и общие параметры:  theme: Объявление токенов темы, которые самостоятельно соотносятся с CSS-параметрами. media: Объявление брейкпоинтов для адаптивной верстки. utils: Создание уникальных функций-утилит для удобства добавления стилей. prefix: Добавление префикса для избежания конфликтов. themeMap: Добавление соотношений кастомных токенов к CSS-параметрам. Странно, что в других библиотеках темизация спрятана где-то в разделах Advanced, тогда как это уже практически стандарт для сайтов и приложений. На этом приятные моменты не закончились. Токены в этой библиотеке — не что-то эфемерное, как переменные в том же SASS, а использование нативных CSS variables! Достаточно на верхнем уровне передать значения новых токенов, а сами компоненты уже нативным CSS сменят свои стили. Пропустим разбор брейкпоинтов — с ними создавать адаптивный дизайн здесь очень легко. Лучше перейдем к важнейшей части любой библиотеки компонентов, когда дизайн выходит за рамки готовой реализации и разработчикам приходится создавать кастомы самостоятельно. С кастомизацией у stitches также нет проблем — это крайне нативный процесс, происходящий с помощью обертки styled или добавления CSS-пропса. При этом любой вариант кастомизации поддерживает работу токенов. Отдельно стоит отметить простоту использования тем: базовая создается в стартовой конфигурации, а все последующие поверх уже перезаписываются токенами. Нужно лишь на верхнем уровне приложения добавить класс созданной темы. При этом внутри компонентов идет привязка токенов по объекту темы, поэтому при потере каких-либо токенов тайпскрипт сразу укажет на эту проблему.  Соответственно, для продуктовых команд можно предложить кастомизировать токены темы, не опасаясь их потерять. А предоставив доступ к низкоуровневому API компонентов, мы расширяем возможности кастомизации нашего набора компонентов до предела. Но об этом в другой раз :) Итого, при использовании этого подхода получаем следующее: Плюсы: Типизация и подсказки. Вариативность стилей по канонам БЭМ. Нативный стайлинг внутри JS/TS. Темы переключаются на лету. Отличная документация. SSR поддерживается, но есть нюансы. Из минусов — рендер стилей только после загрузки JS. Более чем за шесть месяцев работы со stitches мы столкнулись только с одной проблемой — случайным порядком вариантов при генерации классов. Например, компонент Input имеет булевые варианты Error и Disabled, и стили первого перекрывали стили второго. А нам нужен как раз обратный эффект. Решением этой проблемы стало банальное добавление !important или использование compoundVariants. Но в будущем рассчитываем, что ситуацию исправит добавление поддержки CSS layers в библиотеку. В остальном stitches отлично подошла под требования в рамках дизайн-системы. В следующей статье расскажем о применении библиотеки в нашей архитектуре. До встречи!