Всем привет. Меня зовут Дмитрий Пашкевич и я Frontend разработчик в Quadcode. Последние несколько лет я занимаюсь тем, что принято в современной индустрии называть «Дизайн-системами».

В какой-то степени это сочетание слов стало собирательным, так как опыт показывает, что в разных компаниях под ним понимают разное. Понимание зависит от: уровня зрелости команды/проекта/компании/процессов, наличия желания, времени и ресурсов, а самое главное — людей с «горящими» глазами, которые будут это направление развивать, несмотря на все сложности.

Я прошел путь от создания различных UI-китов, трансформаций этих UI-китов в дизайн-системы до полноценного построения дизайн-систем с нуля со стороны FE-разработки в качестве:

  • Потребителя компонентов.

  • Разработчика компонентов.

  • Лида на построении дизайн-системы с нуля. Здесь 80-90% времени занимала разработка компонентов, остальные 10-20% — применение компонентов в продуктовом коде, а также шаринг знаний и взаимодействие с FE-командой разработки.

  • Продуктового разработчика – когда «пилишь компоненты» и сразу же внедряешь их при разработке продукта. В этом случае вся команда участвует в работе над дизайн-системой.

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

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

Спойлер

Кому не терпится узнать отличия дизайн-системы от UI-кита, может сразу перейти к разделу «Что же такое дизайн‑система, если резюмировать». Но все-таки рекомендую читать от и до ????

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

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

Итак, что же это могут быть за проблемы?

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

2. Старый дизайн/интерфейс морально устарел и нужно делать редизайн. Тут встает вопрос, а что делать? Менять текущий продукт: модульно, постранично или создавать с нуля, и т. д. — каждый выбирает свой путь. У разных путей есть нюансы, с которыми придется мириться.

3. Коммуникации по созданию фичи/правкам в интерфейсе превышают разумные пределы. В данном случае создание нового элемента или UX-подхода резко выбивается из продукта. Думаю, это можно рассмотреть как продолжение пункта 2 и желание команды выдавать пользователю более удобный и современный продукт.

4. Любое создание новой фичи (даже похожей) занимает много времени. На это могут влиять разные факторы, например, плохая архитектура, которая перетекла с MVP проекта; устаревшие инструменты и невозможность просто обновиться.

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

6. Наличие большой рутинной работы при создании новых макетов или верстке в рамках одного продукта. Бывает так, что нет возможности переиспользовать UI-кит в дизайне или коде. Чаще такая ситуация возникает в рамках разных проектов, реже в рамках одного (больше относится к дизайну в каком-либо инструменте). Выглядит это примерно так: открываешь новый лейаут дизайна, видишь похожие элементы, но названия другие. Разработчику становится сложно матчить элементы с кодом, и появляется потребность как-то все унифицировать, чтобы не тратить время на ненужное выяснение деталей, когда нужно просто взять, сделать и использовать.

7. Есть пул продуктов компании, и в какой-то момент появляется потребность унифицировать UI/UX. На каждом продукте своя команда дизайнеров и разработчиков. И что, каждая команда будет разрабатывать свой UI-кит? Бывает и так. Тогда внедрение дизайн-системы может начаться со стороны дизайна, который приходит к единому виду. Как следствие, появится несколько UI-китов в коде из-за сопротивления в разных командах, а спустя еще пару итераций начинает рождаться единая компонентная база.

Описанные проблемы не распределены по порядку или важности, любая из них может стать отправной точкой к созданию дизайн-системы.

Фазы формирования дизайн-системы

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

Все это идет следующим образом:

  1. Выделяются человеческие и временные ресурсы.

  2. Формируются требования к стеку технологий, который будет отвечать современному вызову.

  3. На основе требований выбирается стек. Появляются первые demo-версии скелетонов проекта.

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

  5. Зарождается ядро дизайн-системы или, как в это время правильнее говорить, UI-кита, ведь процессам еще только предстоит сформироваться.

  6. Появляются первые компоненты.

  7. Компоненты обкатываются на первой продуктовой фиче, в них вносят правки.

  8. Происходит органическое развитие компонентов в дизайне и коде — с дизайн-ревью или без.

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

    • выявляются и решаются проблемы;

    • появляются новые процессы (синки – встречи о том, как дизайнеры делают дизайн, фронтендеры делают фронтенд, QA тестируют фронтовую часть приложения, кто как взаимодействует с дизайн-макетами);

    • внедряются новые инструменты.

  10. Постепенно наступает фаза, когда команда дизайн-системы или ответственные за дизайн-систему люди делают меньше новых компонентов и больше собирают страницы и занимаются поддержкой компонентов. 

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

Фазы разработки дизайн-системы

Если пройти по этому списку детальнее то, получатся следующие фазы разработки:

Горячая фаза, когда компоненты могут претерпевать максимальное количество изменений в дизайне/коде при внедрении их в конечный продукт. Может длиться от нескольких месяцев (в среднем от 6) до нескольких лет. Минимум, которого на моем опыте удавалось достичь, — 3 месяца, максимум — 1.5 года. Все зависит от стартовых договоренностей, опыта в команде разработки и бизнеса, который выделяет ресурсы, время и формирует приоритеты.

  1. Развитие компонентов в коде и дизайне происходит параллельно. У вас есть коннект между разработкой и дизайном, вы устаканиваете общий язык, нейминги компонетов, как лучше раскладывать библиотеку, стараетесь, чтобы все в макетах ссылалось на базовые компоненты или более сложные компоненты строились из базовых. 

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

  3. Развитие процессов работы с дизайн-системой для дизайна и FE-разработки происходит параллельно. Они улучшают свое, вы улучшаете свое, и постепенно начинаете двигаться бок о бок, когда решите собственные проблемы.

Фаза синка

  1. У вас появляются общие синки, например раз в неделю, или спринт, где дизайн и разработка обсуждают проблемы/вопросы/предложения и договариваются о небольших шагах по улучшению взаимодействия друг с другом.

  2. Иногда фаза синка может прийти в тупик, когда вы начинаете немного завариваться в собственном соку и нужно поделиться с проблемами с кем-то третьим, кто не погружен так сильно в контекст. Такой человек поможет быстрее найти решение проблем.

  3. Устраняются недостатки в процессах связанных с:

    • нехваткой времени на дизайн-ревью, как оно проходит со стороны дизайна, как/что/с помощью чего они смотрят; 

    • критичностью правок по дизайну — что точно нужно делать в первую очередь;

    • несоответствием макетов дизайну и сжатыми сроками релиза;

    • непониманием, как происходят процессы в дизайне при создании компонентов в Figma или наоборот, если дизайн не знает, как компоненты превращаются в код.

Фаза плато

  1. Создание новой страницы/фичи/правки не вызывает переработки ключевых компонентов дизайн-системы или вызывает минимальные изменения.

  2. Возможны крупные изменения в поведении компонентов. Например, переосмысление UI/UX, когда мы понимаем, что что-то неудобно и нужно переделывать или внедрять новые компоненты с других поведением. 

  3. Время от времени — создание новых компонентов.

Мы, при разработке редизайна нашего продукта прошли через все эти стадии осознания и принятия в достаточно быстром темпе: за полгода собрали рабочий продукт, а не только компоненты.

Отмечу, что все три фазы могут повторяться время от времени в зависимости от требуемых изменений. Например, при выделении компонентов в отдельную библиотеку, добавлении управления темами, формировании более строгих стандартов создания компонентов или внедрении в новый проект.

Формирование требований к продукту и (как следствие) к дизайн-системе

Процесс формирования требований к продукту начался с того, что со стороны FE-команды мы выбрали подходящие инструменты для реализации всего проекта (не только дизайн-системы) под минимальные требования:

  • React:

    • для главной страницы необходим Server Side Rendering;

    • для кабинета пользователя Client Side Rendering.

  • TypeScript.

  • Должна быть работа с REST/GraphQL/Web Sockets.

  • Поддержка SSR.

  • React-компоненты должны быть покрыты тестами.

  • Необходимо использовать современный стек по инструментам транспиляции — Babel/Esbuild и т.п.

  • Обязательное наличие линтеров и код-стайла (анализатора кода).

  • Зафиксированная структура папок проекта и принятие соглашения о том, как размещать код. 

  • Опционально: использовать UI-кит и переиспользовать его для компонентов.

  • Опционально: должна быть возможность просмотреть UI-кит проекта и предоставить его дизайнеру.

Итогом этого выбора стало:

  1. React + Typescript.

  2. Eslint и набор правил, которые хотелось бы использовать.

  3. GraphQL — Apollo.

  4. TanStack Query. 

  5. Schema-first подход при разработке API, генерация из Swagger-схемы через openapi-typescript.

  6. Styled-components.

  7. Сборщик для проектов Vite.

  8. Storybook для отображения компонентов.

  9. В качестве пакетного менеджера оставили стандартный npm (рассматривали Yarn/pnpm/npm).

  10. Монорепа, выбор пал на NX .

  11. Архитектура и структура кода Feature-Sliced Design.

  12. Тестирование:

  • unit-тесты;

  • Jest (но потом очень плавно перешли на Vitest);

  • RTL / snapshot.

  1. Мониторинг Sentry.

На этом этапе еще думали над UI-китом и тем, как будем его строить:

  1. Возможно работать с формами через react-hook-form.

  2. Использовать styled-system.com для построения UI / или полностью с нуля / рассмотреть альтернативные варианты.

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

Спустя еще какое-то время (потраченное на ресерч и жаркие обсуждения) появилось решение. Выбор пал на Mantine, хотя мы рассматривали и другие варианты: Ant Design, Chakra UI, Semantic UI. Сердечко покорила документация проекта и не только. В следующем разделе я подробно расскажу, чем же нам так понравился этот инструмент. Этот выбор стал отправной точкой к работе над дизайн-системой. Уже тогда появилось ощущение, что это будет абсолютно новый опыт.

Результат работы с требованиями или почему Mantine

Результатом изысканий стал черновой вариант скелетона приложения. Вы можете посмотреть пример на Github. Финальное решение отличается от того, что представлено в репозитории, но концепция отражена. После скелетона мы приступили к работе над дизайн-системой.

Разработку дизайн-системы начали с выделения базовых элементов:

  • палитры цветов;

  • типографики;

  • отступов;

  • иконок / изображений;

  • бордеров;

  • радиусов;

  • паттернов / флоу построения UI/UX;

  • анимаций.

На основе этого на старте выстроили конфиг для темизации (а уже сейчас постепенно выстраиваем систему дизайн-токенов).

Как уже упоминал выше, под капотом нашей дизайн-системы используется Mantine. Чем же он оказался так полезен? Кажется, что с одной стороны это ограничение, потому что мы завязываемся на инструмент, а с другой?

Понятный и гибкий инструмент

А с другой стороны, этот инструмент предоставляет понятную:

  • документацию;

  • темизацию;

  • типизацию;

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

  • большой набор базовых, хорошо кастомизируемых компонентов, а главное, компонентов, которые прошли испытание в проектах и имеющих комьюнити, что говорит о том, что большая часть типичных кейсов покрыта, поймано достаточное количество багов, чтобы это использовать в проде;

  • разбитые на слои компоненты, где почти каждый слой поддается стилизации и кастомизации. Опять же, если нужно сделать что-то специфичное, всегда можно взять исходный код на базовых элементах и кастомизировать его у себя или сделать pull request.

По сути, для нас Mantine служит фундаментом для построения «дома» = дизайн-системы.

Скорость разработки

Если сравнивать затраты на создание компонентов с нуля и с использованием Mantine, то это выглядит так.

С нуля (в условиях ограниченного времени):

  1. Вы придумываете логику, как будет работать компонент в разных состояниях (default/active/focus/disabled/ и пр.), — программируете логику/стили.

  2. Придумываете как это возможно будет стилизовано снаружи (обычно про это на старте не думают/не подозревают), а потом там нужно чуть-чуть по другому, здесь нужно по другому и т.д. – компонент на слои никто не раскладывает (каждый слой/элемент слоя - должен поддаваться стилизации)

  3. а есть еще разные варианты компонента, для них тоже нужно реализовывать логику и стили:

    • часто, в силу ограниченности времени, может получиться не очень удобное в использовании и последующей модификации API.

Если использовать Mantine:

  1. У вас есть готовый базовый компонент, разложенный по слоям с уже заложенными состояниями (default/active/focus/disabled/и пр.) и логикой поведения. Это, по сути, ваше ограничение, и безопасность на входе = создании компонента.

  2. Вы просто стилизуете компонент под вашу тему.

  3. Стилизация вариантов сводится к тому, чтобы описать разные стили для отображения на основе уже известных классов для слоев.

  4. Если нужна какая-то нестандартная логика, то ее можно довольно легко реализовать через стандартное API компонента или модификацию исходного кода, но уже у себя.

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

По некоторым прикидкам создание финального  компонента на основе Mantine примерно в 5-10 раз быстрее, нежели его полная сборка с нуля. Это достигается за счет того, что:

  1. Сразу понятно, какие параметры и слои есть у компонента.

  2. Можно интерактивно посмотреть компонент в документации: ты получаешь представление о его возможностях и ограничениях + достаточно понятный исходный код.

  3. Можно сразу начать использовать компонент, не придумывая его логику с нуля, а используя предлагаемое API (оно в 80-90%, а в большинстве случаев даже в 100%, закрывает все потребности в логике отображения).

Слоистое API

Давайте рассмотрим слои на примере обычной кнопки. С виду – ну что там сложного? А вот как она выглядит в слоях:

  1. root

    1. inner

      1. icon + left icon

      2. label

      3. loader

      4. icon + right icon

Или более сложный компонент Select, разложенный на слои с возможностью модификации рендера выпадающего списка и пр.

А свои кастомные компоненты можно создавать по следующим правилам:

Примеры кода можно увидеть в соответствующем разделе.

Влияние обновления версий Mantine

Скелетон нашего проекта, а потом и часть сетапа были созданы с помощью 4-й версии Mantine, мы довольно безболезненно пережили обновление на 5-ю версию, и скоро нам предстоит обновиться на 6-ю версию. Думаю, это будет сделать посложнее, но ребята написали очень подробный CHANGELOG в качестве помощи.

Профит

Mantine — это про то, чтобы выдавать больше результата, делая меньше.

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

Наша очень горячая фаза разработки и дизайна длилась примерно один квартал. При этом были готовы 96% компонентов, собран каркас приложения со всевозможными провайдерами (авторизации, переводами и пр.) и реализовано несколько разделов, связанных с авторизацией и онбордингом. 

Фаза активного синка заняла еще один квартал. Появилось несколько новых компонентов (не больше 10), а все основное время было потрачено на сборку страниц.

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

Что же такое дизайн-система, если резюмировать

Хочется подвести небольшой итог и все-таки дать определение, что же такое дизайн-система.

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

Разработка дизайн-системы это про (команду):

  • Единый источник правды по UI/UX и текстам в интерфейсе.

  • Гибкость/стандартизацию/простоту.

  • Продуманность/эффективность/прозрачность.

  • Безопасность изменений/консистентность/наследуемость.

  • Автоматизацию (не обязательно на первых порах).

  • Доступность.

  • Постоянную коммуникацию.

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

Ну и в конечном счете дизайн-система — это:

  • Правила коммуникации.

  • Визуальный язык.

  • Документация.

  • Библиотека компонентов.

Надеюсь, это дало понимание, что UI-кит — это просто библиотека компонентов, и без всего остального его никак нельзя назвать дизайн-системой.

Что принесла дизайн-система и кому она полезна

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

Предлагаю посмотреть на то, что мы в итоге получили спустя 3 квартала работы над дизайн-системой и продуктом.

Каждый участник команды в дизайн-системе нашел для себя ценность:

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

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

  • Разработке унифицированный дизайн и компоненты позволили практически не писать стили внутри проекта. Доля файлов стилизации составляет менее 4%, что ускоряет разработку и выпуск новых страниц в разы (time to market).

  • Для разработки интерфейс пользователя собирается как конструктор, мы уделяем больше времени логике приложения, нежели его верстке.

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

  • Довольно удобно организовано тестирование: есть дизайн-ревью, потом тестирование задачи / фичи. Если возникают правки, то они реализуются и в Figma, и в Storybook. Например, ребята QA при тестировании чаще всего используют Figma и заглядывают в Storybook, чтобы посмотреть какие-то свойства и возможности компонента.

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

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

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

Онбординг новых сотрудников. При онбординге новые сотрудники получают понятное представление о возможностях используемых в проекте компонентов. Могут посмотреть интерактивные примеры их работы, прочитать документацию.

Унифицированное решение в разных проектах. Не нужно привыкать к новому флоу работы интерфейсов.

  • Использование дизайн-системы помогает создать унифицированный дизайн, что улучшает восприятие продукта пользователем. Строгие правила оформления и использование единого стиля во всем проекте обеспечивают единообразный пользовательский интерфейс и позволяют сделать проект более узнаваемым.

Быстрая адаптация к изменениям. Это больше актуально для дизайна, для разработки это более трудоемкий процесс, если API компонента не совместимо с предыдущей версией компонента. Дизайн-система позволяет быстро адаптироваться к изменениям в проекте. Если изменения вносятся в компонент, то это изменение автоматически будет применяться во всех местах, где он используется, что ускоряет процесс адаптации.

Технический стек команды не разрастается. Фокусировка остается на собственной реализации UI-kit. Продукт выполнены в единой стилистике, хоть и состоит из множества сервисов. Не нужно учить новый фреймворк/версию другой библиотеки. 

Выше были перечислены основные плюсы, которые мы получили как команда. Но, конечно же есть и не минусы, а скорее особенности на которые стоит обращать внимание:

  • Сложно синхронизировать изменения компонентов в Figma и в коде.

  • Стартовать продукт сложнее, так как сначала нужно разработать компоненты, только потом бизнес начинает получать итерационно полноценные страницы приложения. Но это справедливо для первых двух-трех итераций внедрения UI-kit в новые проекты, которые требуют решить сопутствующие несоответствия при подключении: настройки, стилизация, документация, версионирование и пр. Но в целом – это решаемая проблема и с каждым новым проектов старт ускоряется в разы.

  • Не всегда просто поддерживать компоненты как библиотеку: версионирование и применение новых версий для всех проектов, их тестирование и пр. может отнимать большое кол-во ресурсов. Особенно на старте, когда требования могут меняться довольно часто.

Планы по развитию дизайн-системы

А что же дальше? А дальше мы хотим*:

  • Выделить компоненты в отдельный пакет:

    • внедрить версионирование в коде;

    • внедрить версионирование в дизайне.

  • Начать внедрение дизайн‑системы в другие проекты команды:

    • подключить и решить сопутствующие проблемы;

    • разработать новые компоненты и улучшать текущие.

  • Обновиться на 6 версию Mantine.

  • Внедрить дизайн‑токены для ключевых компонентов.

  • Внедрить управление цветовой схемой.

  • Описать стандарты создания компонентов и весь их жизненный цикл.

  • Начать описывать контексты и правила использования компонентов.

*На момент публикации статьи часть из этого уже будет сделана.

Примеры кода

  1. Конфига ES Lint

  2. Стилизации Stats компонента

  3. Базовый скелетон проекта (финальное решение отличается от того, что представлено в репозитории, но концепция отражена).

Комментарии (3)