{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "Здравый смысл Дени | Блог: заметки с тегом Дизайн-система",
    "_rss_description": "О дизайне, медиа, мире",
    "_rss_language": "ru",
    "_itunes_email": "",
    "_itunes_categories_xml": "",
    "_itunes_image": "",
    "_itunes_explicit": "",
    "home_page_url": "https:\/\/blog.denislykin.ru\/tags\/dizayn-sistema\/",
    "feed_url": "https:\/\/blog.denislykin.ru\/tags\/dizayn-sistema\/json\/",
    "icon": "https:\/\/blog.denislykin.ru\/pictures\/userpic\/userpic@2x.jpg?1783580338",
    "authors": [
        {
            "name": "Денис Лыкин",
            "url": "https:\/\/blog.denislykin.ru\/",
            "avatar": "https:\/\/blog.denislykin.ru\/pictures\/userpic\/userpic@2x.jpg?1783580338"
        }
    ],
    "items": [
        {
            "id": "5",
            "url": "https:\/\/blog.denislykin.ru\/all\/contrust-design-system\/",
            "title": "Contrust Design System: как объединить 15+ строительных модулей в одну продуктовую систему",
            "content_html": "<h3><a href=\"https:\/\/denislykin.ru\/?space=blog\">→Статья переехала в новый блог<\/a><\/h3>\n<p>⏳ <i>Время чтения ±15 минут<\/i><\/p>\n<p>Сейчас я старший продуктовый дизайнер с восьмилетним опытом, но для того, чтобы понять, как функционирую сложные системы и процессы, мне понадобилось пройти через множество задач и преобразований. Одной из таких задач стала собственная, «ванильная» дизайн-система, которая была разработана не для работы тысяч клиентов, а для удобной навигации строителей, инженеров и внутренних сотрудников строительных компаний. Как часто это бывает — идея была здравая. Её реализация тоже не подкачала, но сейчас, глядя на весь пройденный путь, я чётко вижу моменты, которые я бы отработал иначе.<\/p>\n<h3>Кому будет полезно?<\/h3>\n<p>В первую очередь дизайнерам, работающим с нестандартными интерфейсами. Нестандартный интерфейс в данном случае тот, который содержит неочевдиные механизмы — 3D пространство, объёмные массивы данных, связи «многие-ко-многим». Ещё дизайнерам, лидам и овнерам, которые размышляют над тем, нужна ли им собственная дизайн-система вообще. Ну и наконец тем, кто уже работает с дизайн-системой и размышляет над её масштабированием.<\/p>\n<h3>Контекст<\/h3>\n<p>В 2020 году один из крупнейших застройщиков Санкт-Петербурга имел свой научно-технический центр, отвечающий за цифровизацию процесса строительства. На тот момент уже широко был развит BIM — система 3D моделирования строительных объектов, хранившая внутри моделей плотный слой информации о будущем здании. Компании требовался веб-дизайнер, так как весь сервис проектировался в вебе. Эту позицию я и занял, начав постепенно разбираться в сути. Сервис на тот момент не существовал как что-то целое и единое: это был набор различных инструментов, нацеленных в первую очередь на пачку прозрачных отчётов.<\/p>\n<p>Первым крупным цифровым инструментом был модуль безопасности. Инженеры обходили строительные площадки, фиксировали нарушения на бумаге, а затем переносили информацию в BIM-модель на рабочем компьютере. Позже процесс частично перевели на планшеты, что позволило отмечать нарушения непосредственно на объекте.<\/p>\n<p>В течение следующих месяцев к модулю безопасности добавились документооборот, пожарная безопасность, передача квартир покупателям, исполнительная документация, технический надзор и другие сервисы. Всего в продуктовом контуре появилось более 15 модулей.<\/p>\n<p>Команда на старте состояла из пяти разработчиков, двух frontend- и трёх backend-инженеров, а также группы специалистов строительного профиля. Проектирование интерфейсов в основном выполняли сами инженеры. Их основной задачей было перенести сложные строительные процессы в цифровую среду. Системное проектирование пользовательского интерфейса в этот процесс не входило.<\/p>\n<h3>Исходное состояние интерфейсов<\/h3>\n<p>Каждый модуль развивался как отдельный инструмент. Новая функция обычно проектировалась под конкретную задачу и сразу передавалась в разработку.<\/p>\n<p>UI-kit отсутствовал. Разработчики использовали базовые элементы frontend-фреймворков, дополняя их локальными компонентами. Большая часть решений создавалась заново.<\/p>\n<p>В интерфейсах накопились типовые проблемы:<\/p>\n<ul>\n<li>▸ одинаковые действия выглядели и работали по-разному;<\/li>\n<li>▸ использовались несвязанные между собой иконки;<\/li>\n<li>▸ не было единой типографической шкалы;<\/li>\n<li>▸ интервалы и размеры элементов задавались локально;<\/li>\n<li>▸ цветовые решения не учитывали требования контрастности;<\/li>\n<li>▸ отсутствовали единые правила для таблиц, форм, модальных окон и состояний;<\/li>\n<li>▸ иерархия данных зависела от конкретного модуля;<\/li>\n<li>▸ компоненты разрабатывались под один сценарий и редко переиспользовались.<\/li>\n<\/ul>\n<p>Например, формирование отчёта, экспорт отчёта и фиксация нарушения могли быть реализованы тремя разными способами. В одном модуле использовалась кнопка, в другом иконка, в третьем действие находилось внутри выпадающего меню.<\/p>\n<p>Для пользователей это увеличивало время освоения новых модулей. Для разработки это означало поддержку большого количества одноразовых решений.<\/p>\n<p>Каждая новая задача порождала новый интерфейс, новую frontend-реализацию и новый слой legacy.<\/p>\n<h3>Постановка задачи<\/h3>\n<p>Изначально задача не формулировалась как создание дизайн-системы.<\/p>\n<p>Необходимо было объединить разрозненные сервисы научно-технического центра в единый продукт. Для этого требовалось одновременно систематизировать несколько уровней:<\/p>\n<ul>\n<li>▸ бренд;<\/li>\n<li>▸ ролевую модель;<\/li>\n<li>▸ интерфейсную систему;<\/li>\n<li>▸ принципы интернационализации;<\/li>\n<li>▸ единую точку входа;<\/li>\n<li>▸ правила масштабирования продукта.<\/li>\n<\/ul>\n<p>Дизайн-система стала инфраструктурной частью этой работы.<\/p>\n<p>Её основные цели:<\/p>\n<ol start=\"1\">\n<li>Снизить количество локальных интерфейсных решений.<\/li>\n<li>Ускорить проектирование новых модулей.<\/li>\n<li>Сократить объём повторной frontend-разработки.<\/li>\n<li>Зафиксировать единые правила для desktop и tablet.<\/li>\n<li>Создать общий язык между внутренней командой, подрядчиками и разработкой.<\/li>\n<li>Обеспечить постепенную миграцию существующих продуктов без полной переработки legacy.<\/li>\n<\/ol>\n<h3>Build or adopt<\/h3>\n<p>На первом этапе мы рассматривали два варианта:<\/p>\n<ul>\n<li>▸ использовать готовую UI-библиотеку;<\/li>\n<li>▸ создать собственную дизайн-систему.<\/li>\n<\/ul>\n<p>Основным аргументом в пользу собственной системы была BIM-модель.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/blog.denislykin.ru\/pictures\/BIM.png.jpg\" width=\"2560\" height=\"1244\" alt=\"\" \/>\n<div class=\"e2-text-caption\">Стандартное отображение BIM-модели<\/div>\n<\/div>\n<p>Продукт содержал большое количество сценариев, связанных с 3D-пространством: навигацию, выбор элементов, фильтрацию, работу со слоями, фиксацию нарушений, назначение статусов и групповые операции.<\/p>\n<p>Мы предположили, что готовая библиотека не сможет покрыть эти сценарии без существенных ограничений.<\/p>\n<p>Дополнительными факторами были:<\/p>\n<ul>\n<li>▸ одновременная поддержка desktop и tablet;<\/li>\n<li>▸ работа инженеров непосредственно на строительных площадках;<\/li>\n<li>▸ высокая плотность данных;<\/li>\n<li>▸ необходимость крупных интерактивных зон для планшета;<\/li>\n<li>▸ нестандартные режимы взаимодействия с BIM-viewer.<\/li>\n<\/ul>\n<p>На основе этих вводных было принято решение создать собственную систему.<\/p>\n<p>При проектировании foundations я анализировал Ant Design, Gravity и Fluent. Из этих систем были взяты устойчивые принципы построения компонентов, состояний, типографики и иерархии. Визуальные и технические параметры адаптировались под Contrust.<\/p>\n<p>Ретроспективно это решение оказалось частично ошибочным. Специфические сценарии действительно требовали собственной систематизации, но большинство базовых компонентов можно было построить поверх существующей библиотеки.<\/p>\n<h3>Архитектура дизайн-системы<\/h3>\n<p>Система состояла из нескольких уровней:<\/p>\n<ol start=\"1\">\n<li>Foundations.<\/li>\n<li>Tokens.<\/li>\n<li>Primitive components.<\/li>\n<li>Composite components.<\/li>\n<li>Product patterns.<\/li>\n<li>Domain patterns.<\/li>\n<li>Product modules.<\/li>\n<\/ol>\n<p>Такое разделение позволяло отделить общие правила интерфейса от специфики строительных сценариев.<\/p>\n<h3><b>Foundations<\/b><\/h3>\n<p>В foundations вошли:<\/p>\n<ul>\n<li>▸ цветовая система;<\/li>\n<li>▸ типографика;<\/li>\n<li>▸ spacing;<\/li>\n<li>▸ radius;<\/li>\n<li>▸ borders;<\/li>\n<li>▸ surface;<\/li>\n<li>▸ elevation;<\/li>\n<li>▸ grid;<\/li>\n<li>▸ iconography;<\/li>\n<li>▸ размеры интерактивных элементов;<\/li>\n<li>▸ правила для desktop и tablet.<\/li>\n<\/ul>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/blog.denislykin.ru\/pictures\/DS-Slide-01.png.jpg\" width=\"2560\" height=\"1881\" alt=\"\" \/>\n<\/div>\n<p>Для типографики использовался PT Root UI. Гарнитура хорошо работала с кириллицей, выдерживала высокую плотность интерфейса и могла свободно использоваться в продукте.<\/p>\n<p>Типографическая шкала строилась с коэффициентом 1,25. Для малых размеров применялся увеличенный интерлиньяж в 140%. По мере роста размера текста относительный интерлиньяж уменьшался пропорционально.<\/p>\n<p>Цветовая модель разделялась на три уровня:<\/p>\n<ul>\n<li>▸ primitive colors;<\/li>\n<li>▸ semantic colors;<\/li>\n<li>▸ component tokens.<\/li>\n<\/ul>\n<p>Например:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">Blue \/ 600\n→ Action \/ Primary\n→ Button \/ Background \/ Primary<\/code><\/pre><p>Это позволяло менять визуальные параметры без ручной переработки каждого компонента.<\/p>\n<h3><b>Tokens<\/b><\/h3>\n<p>Для токенов использовался собственный префикс. Через них описывались:<\/p>\n<ul>\n<li>▸ цвета;<\/li>\n<li>▸ размеры;<\/li>\n<li>▸ отступы;<\/li>\n<li>▸ радиусы;<\/li>\n<li>▸ границы;<\/li>\n<li>▸ типографика;<\/li>\n<li>▸ свойства surface;<\/li>\n<li>▸ отдельные component-level значения.<\/li>\n<\/ul>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/blog.denislykin.ru\/pictures\/DS-Slide-02.png.jpg\" width=\"2560\" height=\"1776\" alt=\"\" \/>\n<\/div>\n<p>Токены использовались как общий источник правил для Figma и фронта.<\/p>\n<p>На раннем этапе часть значений существовала как вручную синхронизируемая система. После выхода Variables в Figma мы перевели активную часть UI-kit на переменные.<\/p>\n<p>Миграция заняла около двух недель периодической работы нескольких дизайнеров.<\/p>\n<p>Мы разделили макеты на три категории:<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td style=\"text-align: left\"><b>Состояние<\/b><\/td>\n<td style=\"text-align: left\"><b>Решение<\/b><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left\">Активная работа<\/td>\n<td style=\"text-align: left\">Перевести на Variables<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left\">В разработке<\/td>\n<td style=\"text-align: left\">Перевести на Variables<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left\">Уже выпущенный legacy<\/td>\n<td style=\"text-align: left\">Сверить с токенами, не перестраивать<\/td>\n<\/tr>\n<\/table>\n<p>Полную миграцию старых макетов не проводили. Стоимость такой работы не соответствовала её практической ценности.<\/p>\n<h3>Компонентная архитектура<\/h3>\n<p>Компоненты строились атомарно с использованием nested components и component properties в Figma.<\/p>\n<p>Основной принцип был следующим:<\/p>\n<blockquote>\n<p>Если вложенный элемент мог независимо менять состояние, он оформлялся как отдельный компонент.<\/p>\n<\/blockquote>\n<p>Например, поле ввода могло включать:<\/p>\n<ul>\n<li>▸ label;<\/li>\n<li>▸ input area;<\/li>\n<li>▸ placeholder;<\/li>\n<li>▸ entered value;<\/li>\n<li>▸ leading icon;<\/li>\n<li>▸ trailing action;<\/li>\n<li>▸ helper text;<\/li>\n<li>▸ validation message;<\/li>\n<li>▸ error state.<\/li>\n<\/ul>\n<p>Каждая часть, которая имела собственные варианты или состояния, проектировалась отдельно и затем вкладывалась в основной компонент.<\/p>\n<p>Это позволяло управлять сложным компонентом из одной панели свойств, не разбирая его вручную.<\/p>\n<h3><b>Пример структуры Button<\/b><\/h3>\n<p>Кнопки были представлены примерно в следующих параметрах:<\/p>\n<ul>\n<li>▸ 5 размеров;<\/li>\n<li>▸ несколько визуальных типов;<\/li>\n<li>▸ 4 варианта сочетания текста и иконки;<\/li>\n<li>▸ состояния default, hover, active, disabled, loading;<\/li>\n<li>▸ tablet- и desktop-размерности;<\/li>\n<li>▸ варианты для полноширинного и компактного размещения.<\/li>\n<\/ul>\n<p>Кроме кнопок в систему вошли:<\/p>\n<ul>\n<li>▸ inputs;<\/li>\n<li>▸ dropdowns;<\/li>\n<li>▸ selects;<\/li>\n<li>▸ tooltips;<\/li>\n<li>▸ avatars;<\/li>\n<li>▸ badges;<\/li>\n<li>▸ lists;<\/li>\n<li>▸ tables;<\/li>\n<li>▸ grids;<\/li>\n<li>▸ popovers;<\/li>\n<li>▸ modals;<\/li>\n<li>▸ accordions;<\/li>\n<li>▸ drawers;<\/li>\n<li>▸ rails;<\/li>\n<li>▸ quiz controls;<\/li>\n<li>▸ status components;<\/li>\n<li>▸ navigation controls.<\/li>\n<\/ul>\n<p>При этом количество компонентов не рассматривалось как самостоятельная метрика зрелости системы.<\/p>\n<p>Основным критерием была способность закрывать новые задачи существующими сущностями.<\/p>\n<h3>Компоненты и продуктовые паттерны<\/h3>\n<p>После запуска базовой библиотеки стало понятно, что консистентности на уровне компонентов недостаточно.<\/p>\n<p>Одинаковые элементы могли использоваться в разных последовательностях, с разной логикой и разными состояниями. Поэтому поверх библиотеки компонентов был создан слой продуктовых паттернов.<\/p>\n<p>В него вошли:<\/p>\n<ul>\n<li>▸ сворачивание drawer в navigation rail;<\/li>\n<li>▸ перевод BIM-модели в fullscreen;<\/li>\n<li>▸ режимы модальных окон;<\/li>\n<li>▸ фильтрация;<\/li>\n<li>▸ аккордеоны;<\/li>\n<li>▸ popover-сценарии;<\/li>\n<li>▸ таблицы с bulk actions;<\/li>\n<li>▸ режим выбора элементов модели;<\/li>\n<li>▸ групповые действия;<\/li>\n<li>▸ паттерны статусов;<\/li>\n<li>▸ сценарии работы с планшетом.<\/li>\n<\/ul>\n<h3>BIM Multi Select<\/h3>\n<p>Одним из основных доменных паттернов стал выбор нескольких объектов внутри BIM-модели.<\/p>\n<p>Сценарий состоял из четырёх шагов:<\/p>\n<ol start=\"1\">\n<li>Пользователь открывает модель в обычном режиме навигации.<\/li>\n<li>Включает режим выбора.<\/li>\n<li>Выбирает несколько элементов модели.<\/li>\n<li>Применяет действие ко всей группе.<\/li>\n<\/ol>\n<p>После включения режима кнопка оставалась в активном состоянии. Пользователь мог выбрать 3, 6 или 10 объектов, после чего выполнить групповое действие.<\/p>\n<p>К выбранным элементам могли применяться:<\/p>\n<ul>\n<li>▸ изменение статуса;<\/li>\n<li>▸ создание нарушения;<\/li>\n<li>▸ назначение ответственного;<\/li>\n<li>▸ добавление в проверку;<\/li>\n<li>▸ фильтрация;<\/li>\n<li>▸ включение в отчёт.<\/li>\n<\/ul>\n<p>Для этого паттерна требовалось синхронизировать:<\/p>\n<ul>\n<li>▸ состояние toolbar;<\/li>\n<li>▸ состояние модели;<\/li>\n<li>▸ визуальное выделение объектов;<\/li>\n<li>▸ счётчик выбранных элементов;<\/li>\n<li>▸ доступные действия;<\/li>\n<li>▸ выход из режима;<\/li>\n<li>▸ отмену выбора;<\/li>\n<li>▸ конфликт с native controls viewer.<\/li>\n<\/ul>\n<p>Этот сценарий был специфичен для продукта и действительно требовал собственной системы правил.<\/p>\n<h3>Контроль роста библиотеки<\/h3>\n<p>По мере развития продукта владельцы модулей регулярно предлагали новые элементы.<\/p>\n<p>Одним из примеров была шахматка квартир. Изначально задача выглядела как запрос на новый сложный компонент.<\/p>\n<p>После декомпозиции выяснилось, что интерфейс состоит из трёх уже существующих сущностей:<\/p>\n<ul>\n<li>▸ grid;<\/li>\n<li>▸ badge;<\/li>\n<li>▸ status token.<\/li>\n<\/ul>\n<p>Вместо разработки отдельного компонента мы собрали матрицу квартир из существующих badge-компонентов с заданной сеткой и статусами.<\/p>\n<p>Новый системный компонент не потребовался.<\/p>\n<p>Для принятия подобных решений использовались следующие критерии:<\/p>\n<ol start=\"1\">\n<li>Можно ли решить задачу существующим компонентом.<\/li>\n<li>Можно ли расширить существующий компонент новым variant.<\/li>\n<li>Повторяется ли сценарий в других модулях.<\/li>\n<li>Является ли решение локальным или системным.<\/li>\n<li>Требует ли оно отдельной документации.<\/li>\n<li>Будет ли компонент поддерживаться в Storybook.<\/li>\n<li>Насколько высока стоимость его дальнейшего развития.<\/li>\n<\/ol>\n<h3>Figma, Storybook и документация<\/h3>\n<p>UI-kit существовал в Figma и параллельно переносился в Storybook.<\/p>\n<p>В Storybook фиксировались:<\/p>\n<ul>\n<li>▸ компонент;<\/li>\n<li>▸ его состояния;<\/li>\n<li>▸ варианты;<\/li>\n<li>▸ технические параметры;<\/li>\n<li>▸ правила использования;<\/li>\n<li>▸ ограничения;<\/li>\n<li>▸ примеры.<\/li>\n<\/ul>\n<p>Документация готовилась совместно с frontend-разработкой и техническим писателем.<\/p>\n<p>Таким образом система включала:<\/p>\n<ul>\n<li>▸ Figma UI-kit;<\/li>\n<li>▸ tokens;<\/li>\n<li>▸ Storybook;<\/li>\n<li>▸ текстовую документацию;<\/li>\n<li>▸ brandbook;<\/li>\n<li>▸ правила contribution;<\/li>\n<li>▸ changelog;<\/li>\n<li>▸ governance.<\/li>\n<\/ul>\n<p>Figma не рассматривалась как единственный источник дизайн-системы. Она была рабочим инструментом дизайнеров, но кодовая реализация и документация имели равный статус.<\/p>\n<h3>Работа с распределёнными командами<\/h3>\n<p>К моменту запуска UI-kit к проекту подключились внешние команды дизайна и frontend-разработки.<\/p>\n<p>Из-за ограничений Figma, стоимости лицензий и последующих санкционных ограничений команды работали в разных окружениях.<\/p>\n<p>Централизованное подключение всех дизайнеров к одной библиотеке было невозможно.<\/p>\n<p>Для синхронизации использовался следующий процесс:<\/p>\n<ul>\n<li>▸ головной UI-kit оставался у внутренней команды;<\/li>\n<li>▸ первая страница файла была отведена под changelog;<\/li>\n<li>▸ изменения сопровождались ссылками на конкретные компоненты;<\/li>\n<li>▸ два раза в неделю внешние дизайнеры проверяли обновления;<\/li>\n<li>▸ после синхронизации они оставляли отметку о просмотре;<\/li>\n<li>▸ спорные изменения обсуждались отдельно;<\/li>\n<li>▸ предложения по новым компонентам проходили через внутреннюю дизайн-команду.<\/li>\n<\/ul>\n<p>Такой процесс был частично ручным, но обеспечивал управляемое распространение системы между независимыми командами.<\/p>\n<h3>Где система ломалась<\/h3>\n<p>Основные проблемы возникали не в компонентной архитектуре, а в организации работы.<\/p>\n<p>У каждого модуля был владелец. Обычно это был специалист, хорошо знающий конкретный строительный процесс и связанные с ним юридические, финансовые или операционные риски.<\/p>\n<p>В условиях срочного релиза владелец модуля мог напрямую обратиться к дизайнеру подрядчика и попросить добавить новый элемент.<\/p>\n<p>Типовой сценарий выглядел так:<\/p>\n<ol start=\"1\">\n<li>Владельцу модуля требовалось срочное изменение.<\/li>\n<li>Он передавал задачу внешнему дизайнеру.<\/li>\n<li>Дизайнер создавал новый локальный компонент.<\/li>\n<li>Решение попадало в макет.<\/li>\n<li>Разработчик не находил компонент в UI-kit.<\/li>\n<li>В Storybook и документации его также не было.<\/li>\n<\/ol>\n<p>Такие элементы существовали только внутри одного макета. Для них можно использовать термин orphan components.<\/p>\n<p>Причинами были:<\/p>\n<ul>\n<li>▸ сжатые сроки;<\/li>\n<li>▸ распределённые команды;<\/li>\n<li>▸ локальные договорённости;<\/li>\n<li>▸ скрытые экспертные знания;<\/li>\n<li>▸ отсутствие обязательного review;<\/li>\n<li>▸ давление со стороны владельцев модулей.<\/li>\n<\/ul>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/blog.denislykin.ru\/pictures\/DS-Slide-03.png.jpg\" width=\"2560\" height=\"2304\" alt=\"\" \/>\n<\/div>\n<h3>Governance<\/h3>\n<p>Для контроля новых решений был введён обязательный review на уровне внутренней дизайн-команды.<\/p>\n<p>Любой новый компонент или паттерн должен был пройти следующую проверку:<\/p>\n<h3><b>1. Можно ли использовать существующий компонент?<\/b><\/h3>\n<p>Если да, новая сущность не создавалась.<\/p>\n<h3><b>2. Можно ли расширить существующий компонент?<\/b><\/h3>\n<p>Если задача решалась новым variant или property, обновлялся текущий компонент.<\/p>\n<h3><b>3. Является ли сценарий повторяемым?<\/b><\/h3>\n<p>Если решение использовалось только в одном локальном сценарии, оно могло остаться product-specific pattern.<\/p>\n<h3><b>4. Нужна ли системная сущность?<\/b><\/h3>\n<p>Если решение было повторяемым и применимым в нескольких модулях, оно проходило design review.<\/p>\n<p>После этого выполнялись:<\/p>\n<ul>\n<li>▸ проектирование в Figma;<\/li>\n<li>▸ согласование с frontend;<\/li>\n<li>▸ реализация в Storybook;<\/li>\n<li>▸ подготовка документации;<\/li>\n<li>▸ обновление changelog;<\/li>\n<li>▸ распространение по командам.<\/li>\n<\/ul>\n<p>Governance уменьшил количество несогласованных элементов и зафиксировал единый процесс развития библиотеки.<\/p>\n<h3>Работа с BIM-viewer<\/h3>\n<p>Отдельной проблемой было взаимодействие собственной интерфейсной системы с controls, встроенными в BIM-viewer.<\/p>\n<p>Viewer мог предоставлять собственные инструменты:<\/p>\n<ul>\n<li>▸ навигацию;<\/li>\n<li>▸ работу с камерой;<\/li>\n<li>▸ выбор объектов;<\/li>\n<li>▸ управление слоями;<\/li>\n<li>▸ изоляцию элементов;<\/li>\n<li>▸ скрытие объектов;<\/li>\n<li>▸ измерения.<\/li>\n<\/ul>\n<p>Contrust также содержал controls поверх модели:<\/p>\n<ul>\n<li>▸ фильтрацию;<\/li>\n<li>▸ переключение режимов;<\/li>\n<li>▸ групповой выбор;<\/li>\n<li>▸ назначение статусов;<\/li>\n<li>▸ фиксацию нарушений;<\/li>\n<li>▸ переход к сущности;<\/li>\n<li>▸ работу с карточкой объекта.<\/li>\n<\/ul>\n<p>В результате на одном экране существовали две системы управления.<\/p>\n<p>Необходимо было определить:<\/p>\n<ul>\n<li>▸ какие действия остаются внутри viewer;<\/li>\n<li>▸ какие переносятся в интерфейс Contrust;<\/li>\n<li>▸ какие native controls скрываются;<\/li>\n<li>▸ какие действия перехватываются;<\/li>\n<li>▸ какой режим считается приоритетным;<\/li>\n<li>▸ как избежать конфликта selection states;<\/li>\n<li>▸ как пользователь выходит из модального режима модели.<\/li>\n<\/ul>\n<p>Часть решений пересматривалась несколько раз. Основная сложность заключалась не в визуальном оформлении кнопок, а в согласовании двух interaction models.<\/p>\n<h3>Автоматизация иконок<\/h3>\n<p>Для иконок использовался собственный icon font.<\/p>\n<p>Процесс был частично автоматизирован:<\/p>\n<ol start=\"1\">\n<li>Иконка создавалась в Figma.<\/li>\n<li>Экспортировалась через внутренний плагин.<\/li>\n<li>Добавлялась в шрифт.<\/li>\n<li>Обновление отправлялось в Git.<\/li>\n<li>Frontend-команда получала актуальную версию.<\/li>\n<\/ol>\n<p>После обновления ветки новая иконка становилась доступна в продукте без ручной передачи отдельных SVG-файлов.<\/p>\n<h3>Результат<\/h3>\n<p>В результате была создана полноценная дизайн-система, которая включала:<\/p>\n<ul>\n<li>▸ UI-kit;<\/li>\n<li>▸ foundations;<\/li>\n<li>▸ tokens;<\/li>\n<li>▸ component library;<\/li>\n<li>▸ product patterns;<\/li>\n<li>▸ BIM patterns;<\/li>\n<li>▸ Storybook;<\/li>\n<li>▸ документацию;<\/li>\n<li>▸ changelog;<\/li>\n<li>▸ contribution rules;<\/li>\n<li>▸ brandbook;<\/li>\n<li>▸ governance.<\/li>\n<\/ul>\n<p>Первые три модуля вышли в production с единым визуальным и интерфейсным языком.<\/p>\n<p>Они использовали:<\/p>\n<ul>\n<li>▸ общую точку входа;<\/li>\n<li>▸ единые компоненты;<\/li>\n<li>▸ общую типографику;<\/li>\n<li>▸ стандартные состояния;<\/li>\n<li>▸ одинаковые принципы работы с данными;<\/li>\n<li>▸ согласованную логику desktop и tablet.<\/li>\n<\/ul>\n<p>На этой основе начали разрабатываться следующие модули.<\/p>\n<p>В продуктовом контуре использовалось более 15 сервисов. Дизайн-система позволила перевести их развитие из набора локальных интерфейсных решений в управляемую модель.<\/p>\n<p>Основной качественный результат заключался в том, что новые задачи больше не начинались с пустого файла у дизайнера и новой реализации у frontend-разработчика.<\/p>\n<p>Команды получили общий набор решений, общий процесс согласования и общий источник правил.<\/p>\n<h2><b>Выводы<\/b><\/h2>\n<h3><b>Сначала стандартизировать частое, потом специфичное<\/b><\/h3>\n<p>Большая предметная область не означает, что ей нужна полностью уникальная библиотека компонентов. Большинство базовых задач Contrust закрывались стандартными UI-паттернами. Кастомизация имела наибольшую ценность там, где начиналась специфика продукта: BIM, строительные статусы, проверки и работа инженеров на площадке.<\/p>\n<h3><b>Рост библиотеки сам по себе ничего не доказывает<\/b><\/h3>\n<p>Новый компонент стоит добавлять только тогда, когда существующие компоненты, их свойства и композиции не закрывают задачу. Чем больше сценариев удаётся собрать из уже существующих элементов, тем устойчивее система и дешевле её поддержка.<\/p>\n<h3><b>Governance нужно проектировать вместе с компонентами<\/b><\/h3>\n<p>Даже хорошо организованный UI Kit быстро теряет консистентность, если продуктовые команды могут обходить его при срочных задачах. Changelog, design review, contribution flow и критерии появления новых компонентов оказались не менее важны, чем сами компоненты.<\/p>\n<h3><b>Миграция должна иметь практическую ценность<\/b><\/h3>\n<p>Не каждое изменение дизайн-системы требует обновления всего legacy. Активные макеты имеет смысл поддерживать в актуальном состоянии, а уже выпущенные интерфейсы достаточно проверять на совместимость и обновлять тогда, когда они снова попадают в работу.<\/p>\n<h3>Что не получилось<\/h3>\n<p>Основной ошибкой было решение полностью разрабатывать базовую UI-библиотеку самостоятельно.<\/p>\n<p>Команда вручную проектировала и кодировала:<\/p>\n<ul>\n<li>▸ buttons;<\/li>\n<li>▸ dropdowns;<\/li>\n<li>▸ tooltips;<\/li>\n<li>▸ inputs;<\/li>\n<li>▸ popovers;<\/li>\n<li>▸ базовые состояния;<\/li>\n<li>▸ стандартные controls.<\/li>\n<\/ul>\n<p>При этом большая часть этих компонентов не имела специфики строительного продукта.<\/p>\n<p>Изначальная логика выглядела так:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">Сложный BIM-продукт\n→ нестандартные сценарии\n→ полностью собственная дизайн-система<\/code><\/pre><p>На практике корректная модель была другой:<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">Готовая UI-библиотека\n  - ▸ собственные tokens и theme\n  - ▸ строительные product patterns\n  - ▸ BIM interaction layer<\/code><\/pre><p>После того как внутри компании закрепилось представление о полностью собственной дизайн-системе, отказаться от этой модели стало сложно. Собственная разработка воспринималась как технологическое преимущество и стала частью внутренней коммуникации проекта.<\/p>\n<p>В результате часть ресурсов была потрачена на повторную реализацию стандартных компонентов.<\/p>\n<h3>Что я сделал бы иначе<\/h3>\n<p>Если бы аналогичная система создавалась сейчас, я бы разделил её на два уровня.<\/p>\n<h3><b>Стандартный уровень<\/b><\/h3>\n<p>Основа на базе зрелой библиотеки, например Ant Design:<\/p>\n<ul>\n<li>▸ buttons;<\/li>\n<li>▸ inputs;<\/li>\n<li>▸ dropdowns;<\/li>\n<li>▸ tooltips;<\/li>\n<li>▸ modals;<\/li>\n<li>▸ tables;<\/li>\n<li>▸ popovers;<\/li>\n<li>▸ standard states;<\/li>\n<li>▸ accessibility behavior.<\/li>\n<\/ul>\n<h3><b>Доменный уровень<\/b><\/h3>\n<p>Собственные решения для Contrust:<\/p>\n<ul>\n<li>▸ BIM selection mode;<\/li>\n<li>▸ model filtering;<\/li>\n<li>▸ construction statuses;<\/li>\n<li>▸ apartment matrix;<\/li>\n<li>▸ inspection flows;<\/li>\n<li>▸ object violations;<\/li>\n<li>▸ desktop-tablet adaptation;<\/li>\n<li>▸ interaction between viewer and product UI.<\/li>\n<\/ul>\n<p>Такой подход сократил бы стоимость разработки и поддержки базовых компонентов.<\/p>\n<p>Основные ресурсы можно было бы направить на сценарии, в которых продукт действительно отличался от стандартных enterprise-систем.<\/p>\n<p>Главный вывод проекта состоит в следующем:<\/p>\n<p>Сложность предметной области не требует полной уникальности базового интерфейса. В Contrust специфичными были строительные процессы, BIM-сценарии и работа инженеров на площадке. Кнопки, dropdown и tooltip могли оставаться стандартными.<\/p>\n<h3>Связаться со мной<\/h3>\n<p>Если есть желание обсудить этот кейс, другие кейсы или пообщаться по иным вопросам в сфере продуктового дизайна — пишите мне в <a href=\"https:\/\/t.me\/denyalykin\">телеграм<\/a> или на <a href=\"mailto:i@dlykin.ru\">почту<\/a>. Подробнее обо мне и моей работе можно узнать на <a href=\"https:\/\/denislykin.ru\">моём сайте<\/a>. Сейчас я в поисках продуктовой команды, в которой смогу развивать продукт и быть полезным игроком. Пишите, буду рад пообщаться!<\/p>\n",
            "summary": "⏳ Время чтения ±15 минут",
            "date_published": "2026-08-25T00:55:54+03:00",
            "date_modified": "2026-09-04T17:51:06+03:00",
            "tags": [
                "Дизайн",
                "Дизайн-система",
                "Продукт"
            ],
            "image": "https:\/\/blog.denislykin.ru\/pictures\/BIM.png.jpg",
            "_date_published_rfc2822": "Tue, 25 Aug 2026 00:55:54 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "5",
            "_e2_data": {
                "is_favourite": false,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/blog.denislykin.ru\/pictures\/BIM.png.jpg",
                    "https:\/\/blog.denislykin.ru\/pictures\/DS-Slide-01.png.jpg",
                    "https:\/\/blog.denislykin.ru\/pictures\/DS-Slide-02.png.jpg",
                    "https:\/\/blog.denislykin.ru\/pictures\/DS-Slide-03.png.jpg"
                ]
            }
        }
    ],
    "_e2_version": 4199,
    "_e2_ua_string": "Aegea 11.5 (v4199)"
}