Как мы создавали собственную дизайн-систему для ускорения процессов разработки

a0e46e355851a6e6f95e5077d0dfaeef.jpg

Может ли в 2024 году фронтенд-разработчик не тратить время сперва на изучение макета, а затем на его реализацию в коде, в условиях быстро меняющихся требований бизнес-задач? Да, если использовать готовую дизайн-систему. 

При её отсутствии разработчики либо занимаются копипастом подходящих компонентов из других проектов, либо пользуются шарингом этих компонентов в каком-либо виде (вероятно, даже со сторибуком) —, но такой подход имеет свои минусы.

Ранее мы рассказали об общем процессе создания и внедрения нашей дизайн-системы. Сегодня углубимся в технические подробности — поэтапно рассмотрим, что в ходе разработки происходило под капотом. 

Привет, Хабр! Я Константин, фронтенд-разработчик в Сравни. Эта статья — продолжение нашего рассказа про собственную дизайн-систему. О том, как мы вообще пришли к идее сделать и внедрить нечто подобное, а также о конкретных проблемах, которые хотели решить, можете прочитать здесь (вкратце: требовалось стандартизировать и ускорить процессы разработки). 

Ниже я опишу технические нюансы создания нашей дизайн-системы — в порядке хронологии, с первых дней разработки до этапа её поддержки. 

Этап 1. Закладываем основы дизайн-системы 

В первую очередь мы прошлись по стандартным этапам: развернули среду для удобной разработки, настроили сторибук для визуализации компонентов, сборщик, подключили линтеры и тесты, реализовали удобную публикацию пакета и т.п. Так у нас происходит примерно в каждом новом проекте.

После этого приступили к разработке базовых компонентов. Для нашей дизайн-системы мы использовали атомарный подход. Причина выбора кроется в главном преимуществе этого подхода — наследуемости.

Это когда из атомов (законченные неделимые компоненты: простая кнопка, текст, заголовок, иконка, линк;, а также абстрактные понятия: цвет, шрифт, размер) строятся молекулы (то есть объединения атомов — например, компонент с выпадающим списком или автокомплит), из которых вырастают организмы (совокупность молекул и атомов: сложные формы или модальные окна с логикой). 

Иными словами, атомарный подход — создание некоторого ограниченного набора элементов, на основе которого затем строятся более крупные сущности (модули, шаблоны, страницы).

Наследуемость (читай: переиспользуемость кода) и реализация компонентов дизайн-системы только на нижних двух уровнях (атомы и молекулы) позволило нам собрать минималистичный пакет — около 90 кб. 

76a0cba8a8b3f96cde590ace84213306.jpg

Итак, началась разработка. Первым делом мы запилили типографику (линки, текст, заголовки), кнопки (как же без них), гриды. Далее к процессу подключились дизайнеры — и тут мы все вместе столкнулись с первой  сложностью. Стали очевидны различия в том, как мы смотрим на одни и те же вещи. 

В моем понимании дизайн-система — это, в первую очередь, про правила, и только потом про сами компоненты и визуал. Под правилами я понимаю договоренности, которые мы (бизнес, дизайн и разработка) закладываем в дизайн-систему на старте. Эти правила приводят к некоторому ограничению свободы как для дизайнеров при проектировании интерфейсов, так и для разработчиков при использовании дизайн-системы. 

В каком-то смысле в этом суть дизайн-системы: не разрешать всё, иначе это уже не система. И здесь на старте возник вопрос: как задать правила (ограничения), сохранив кастомизируемость и переиспользование?  

Перед командой дизайна встал свой вызов: научиться создавать «правильные» макеты, с учетом наследования свойств, группировки слоев и прочего.

В результате обсуждений мы пришли к пониманию, что основные свойства компонента можно настроить пропсами (цвет, размер, …), но при этом у разработчиков есть возможность через className или style повесить свои стили на компонент. Использование этой возможности не приветствуется, но допускается, и как показала практика, это очень помогает в определенных случаях (например, когда срок «горит»). 

Примерно так:

d941c426a8ac1b99e6d3f65c645ac851.png

Другой проблемой была путаница с цветом. Изначально цветовая палитра была добавлена в саму дизайн-систему, но в ходе развития проекта и частых правок оттенков со стороны дизайнеров (в поисках идеального варианта), стало очевидно, что все базовые стили и цвета необходимо вынести в отдельную либу. 

Так у нас появился пакет design-system-theme. Там в виде css-переменных представлены цвета для темной и светлой тем, а также другие сущности (отступы, паддинги, размерности, брейкпоинты) Всё это добро добавили и в виде sass, и в less (у нас так исторически сложилось, что некоторые продукты используют sass). 

Была попытка использовать lerna и создать монорепозиторий под все UI-пакеты (сама дизайн-система, пакет с темами и другие пакеты). Однако потенциальные проблемы (версифицирование отдельных пакетов в составе, а также отсутствие понимания возможного профита от этого решения) привели к тому, что от идеи отказались. Если у вас есть положительный опыт такого плана, пожалуйста, расскажите в комментариях.

Всего первый этап продлился 3 месяца. За это время был сформирован костяк из порядка 25 основных компонентов (кнопка, инпут, элементы меню, выпадающий список, селект, автокомплит, карточка, радиокнопки, алерт, календарь, чекбокс и другие), которые, конечно, в дальнейшем много раз перекраивались и допиливались. Так у нас появилась версия 0.1.

4546266fb92a4553f217a1f1ef2a4171.jpg

Этап 2. Развитие

Спойлер здесь такой: развитие было бурным. И цена за это бурное развитие — неизбежное появление багов. Иногда возникало понимание, что то или иное выбранное ранее решение не является оптимальным; тогда приходилось откатываться и выбрать технически более правильный путь. Именно эти две проблемы (баги, поиск приемлемого варианта) были ключевыми на данном этапе. 

Проблему с багами частично решили внедрением тестов, использовали jest. Тут все по классике: для каждого компонента есть базовые тесты, а также отдельный тест на каждый передаваемый пропс. Кроме того, в компонентах-молекулах (например, селект или автокомплит) были добавлены тесты, симулирующие поведение пользователя (например, клик на определенную область компонента или нажатие кнопки). 

Конечно, наличие тестов не гарантирует отсутствие багов, но существенно помогает в дальнейшем. Так было в нашем случае, когда появлялась потребность в рефакторинге  компонентов. Тогда мы автоматически участвовали в эксперименте а-ля TDD; конечно, при условии неизменности уже реализованного поведения самого компонента. И это добавляло некоторой уверенности, что новый код «не должен» ничего сломать на проде. 

Другая проблема этапа развития — ситуации, когда свернули «не туда». Тут главное — не уехать далеко и успеть вовремя развернуться. Например, у нас были попытки завезти в проект linaria, но «не зашло» из-за проблем при сборке проекта, остались на css-модулях. Было опробовано и несколько пакетов с красивой анимацией (пожелание от дизайнеров и бизнеса). Остановились на framer-motion. 

В целом при выборе стороннего пакета следовали таким правилам:  

  • не использовать сторонние пакеты настолько, насколько это возможно (компромисс между трудозатратами на собственную реализацию и »…»);

  • если используем сторонний пакет, то он должен иметь минимальное количество зависимостей (в идеале вообще ни от чего не должен зависеть) и минимальный вес; уже потом оцениваем наличие необходимой функциональности.

Сейчас у нас используется всего 4 подходящих под условия пакета, и это позволило нам не раздувать размер дизайн-системы. 

Ещё про лайфхаки: чтобы не разрабатывать сферического коня в вакууме, необходимо было сразу как-то опробовать свои наработки на практике. Делать это сразу на проде опасно — бизнес может не оценить. Решили сделать такой эксперимент: зарефакторить шапку сайта с использованием новой дизайн-системы, как раз и новый дизайн для них подоспел. 

Сказано — сделано. Накидали компонент шапки прямо в дизайн-системе, в процессе выявили у компонента ряд багов (неучтённые кейсы, неожидаемое поведение), которые сразу же починили. После отладки вынесли шапку в отдельную либу, react-header, где она и живет по сей день. Так же поступили с футером и еще несколькими большими компонентами. Эдакий тест, который позволяет почувствовать себя в роли искушенного пользователя дизайн-системы (разработчика) и обкатать её компоненты. 

Для наглядности — текущая структура проекта с шапкой:

8d93bccda3802406423cbb8ee9854174.png

Этап 3. Поддержка

Этап развития я считаю условно завершённым спустя примерно 6 месяцев, когда первые продуктовые команды начали переходить на использование нашей дизайн-системы. Так формально начался этап поддержки. 

Как полагается, при этом проявились баги, особенности поведения в граничных кейсах, запросы на доработку. Для сбора обратной связи пользователей дизайн-системы завели канал в корпоративном мессенджере; фидбэк поступал ежедневно. 

Пример:

575a787e9d5423b868422cdbfbd079bb.jpg

Завели простое правило: при фиксах или доработках дополняли пул тестов, который реализовывал проверку соответствующего кейса. Времени занимает мало, а польза большая — не наступаем на одни грабли дважды.

Отдельно скажу про запрашиваемые доработки — тут важно соблюсти баланс между функциональностью компонента и его универсальностью. Все продукты, где будет использоваться дизайн-система, нужно видеть в режиме «helicopter view», иметь широкий контекст — в этом нам здорово помог дизайн-директор. 

Другое правило: если компонент используется только одной командой, то он совершенно точно не попадет в дизайн-систему. Напротив, если компонент (или схожие компоненты, которые можно объединить в один) переиспользуется многими, то это кандидат на добавление в дизайн-систему. 

Бывает, что компонент (блок компонентов) не является элементом дизайн-системы, но нужен нескольким командам — в таком случае его нужно пошарить. Так у нас появился репозиторий shared-components, в который любой разработчик может положить реализованный в своем продукте компонент, чтобы облегчить жизнь коллегам.

Как и многие разработчики дизайн-систем из соседних компаний мы столкнулись с проблемой синхронизации кода и макета. В частности, продуктовые дизайнеры могли рисовать макеты, которые не всегда было возможно без доработок реализовать на компонентах дизайн-системы. 

Начали искать причины, выяснили, что макеты дизайн-системы могли редактироваться без уведомления разработчиков — за счёт этого накапливалась рассинхронизация. Чтобы решить проблему, создали эпик в Jira — для аудита соответствия текущего кода дизайну в рамках дизайн-системы, правке кода или макета, и так для каждого компонента. После завершения этой задачи завели правило: если вносишь изменения в макет из дизайн-системы, уведомляешь команду UI и заводишь задачу. Пока что подход работает.

Всего на текущий момент у нас порядка 50 базовых компонентов в дизайн-системе. Все основные продукты переведены на её использование. Заложенная в самом начале возможность темизации позволила малыми усилиями внедрить тёмную тему на сайте (в данном случае проблем было больше у команд, которые не соблюдали правила использования дизайн-системы). 

Недавно я проводил опрос среди коллег, кто пользуется дизайн-системой: «клиенты» довольны. 

b163162a7ffe7ed61687739fb8ba5b4f.jpgc31141bc7bbfdaf672d6621c4dad9dcd.jpg

Также опрос позволил скорректировать план доработок. Были выявлены малоиспользуемые компоненты (которые не очень удобно применять на практике из-за особенностей продукта, например, компонент CountDown) и компоненты, которые вообще не представлены в дизайн-системе, но необходимы (пример: таблицы). Плюс, планируем в следующем мажорном обновлении подготовить компоненты для оптимального использования в react server components.

Персональный путь в тысячу шагов

В сухом остатке: у нас получилось создать систему, компоненты которой с одной стороны имеют фиксированный дизайн (читай: ограничения, чтобы была узнаваемость бренда), а с другой — позволяют их кастомизировать при необходимости в конкретном продукте. Таким образом мы получили комбинацию визуальных правил создания продукта, а не просто набор UI-компонентов. 

Создание и внедрение дизайн-системы — сложный, затратный и во многом уникальный в рамках конкретной компании процесс. Выше я попытался рассказать, как это происходило у нас. Уверен, при реализации подобного проекта в других компаниях могут возникнуть совсем другие проблемы. Было бы интересно почитать о вашем опыте — пишите в комментариях!

© Habrahabr.ru