Как я Делал компоненты в Московской БирЖе
Что: дизайн-система
Где: московская биржа
Роль: продуктовый дизайнер
Цель и задача
Когда я пришёл в Московскую биржу, дизайн-система работала на стилях Figma. После обновления Pixso до версии 2.0 появились токены, и стало понятно — нужен полный рефакторинг системы.

Задача: перевести компоненты на токены, навести порядок в структуре и неймингах пропсов. При этом не сломать сотни макетов у продуктовых команд. Внешне всё должно остаться прежним — размеры, цвета, состояния. Менялось только то, что под капотом.
Проблема
Что было не так:
  • Пропсы назывались по-разному в похожих компонентах;
  • Стили вместо токенов;
  • Ещё и Pixso плохо работала с высоконагруженными компонентами.

Вишенка на торте — при обновлении дизайн-системы не должны были поехать макеты у продуктовых команд. Для них визуально вообще ничего не должно было измениться. Иначе представьте: у сотен инуптов в макетах команд внезапно меняются отступы или скругления углов. Объяснять это дизайнерам было бы сложно.
Решение
Нас было двое из ларца — я да лид Константин (привет тебе, если читаешь). Костя взял на себя миграцию цветов, типографики и размеров в токены — он их заводил до меня и знал систему. Я занялся компонентами. Пообщавшись с командами, расставил приоритеты по компонентам и понял, что первым на очереди будет Form-field. Расскажу про него, и ещё про парочку.
Form-field
Мы приняли радикальное решение: разделили типы Form-field на отдельные файлы. В итоге получилось такие компоненты: Text input, Date picker, Select, Input password — для каждого типа свой файл. Переключение между ними — через библиотеку компонентов. Звучит как костыль, но в будущем это решило проблему производительности и «багованности» у форм.
Каждый form-field собирался из независимых частей. Для этого был создан файл Form-field parts, в котором было:

  • Placeholder — лейбл + текст ввода. Для каждого типа form-field он был свой: для Date picker там были форматы дат (дд.мм.гггг), для Input password доты (••••••••••).
  • Right side. Suffix — текст справа. Action icon — иконки (календарь, лоадинг, глазик)
  • Left side. Prefix — текст слева. Leading icon — иконка-идентификатор (поиск, почта)
  • Caption — подпись под полем
  • Counter — счётчик символов
При этом я всё равно старался не перегружать компонент. Например для Date picker не нужны иконки-идентификаторы слева но нужна экшен кнопка вызова календаря, соответственно в компонент закладывался только Right side. Да, в Figma было бы сильно проще такое делать:)
Collapse
Казалось бы, простой компонент для скрытия контента. Но в реальности он покрывал много разных продуктовых кейсов, и имел внутри себя:
  • Badge — показывает статус или количество объектов внутри раздела. Например: «На проверке», «Есть ошибки» или «3 операции». Подключается как дочерний компонент.
  • Есть Button — запускает отдельное действие с содержимым раздела. Например: «Добавить клиента», «Редактировать данные» или «Скачать отчёт». Подключается как дочерний компонент.
  • Есть Toggle — включает или выключает настройку, связанную с разделом. Например: «Уведомлять об операциях» или «Включить в отчёт». Подключается как дочерний компонент.
  • Имеется два типа: Ghost (без бордера) и Outline (с бордером).
Calendar
Компонент имеет три типа: дни, месяцы, годы.
Каждая ячейка может настраиваться как:
  • Активная — если ткнуть курсором в неё
  • Текущий день — отображение сегодняшнего дня/месяца/года. Элемент выделяется малоконтрастной обводкой для быстрой ориентации.
  • Выходной — текст окрашивается в красный цвет. Актуально только для дней.
  • Неактивная — элемент отображается приглушённым цветом и не реагирует на взаимодействие.
  • Отключенная ячейка — пустая ячейка в сетке. Заполняет пространство в начале или конце месяца. Актуально для дней.
Параметры меняются в зависимости от выбранного типа. Ведь месяц или год не может быть выходными (ну у нас таких кейсов точно не было командах).

Диапазон работает во всех типах. Можно выделить период от-до в любом режиме просмотра.
Кастомные статусы дней — запрос от продуктовой команды. Добавил тип дня «status». Это статусный вариант дня с выбором одного из шести цветов дополнительной палитры. Применяется для категоризации дней по смыслу (дедлайны, отпуска, важные события). Имеет упрощённый набор свойств без поддержки диапазонов и событий: state, color, disable. Теперь можно перекрашивать дни календаря под задачи продукта.
Popover
Расширенная версия всплывающей подсказки или старший бро Tooltip'а.
Имеет пропсы: Title, Edit title, Description, Edit description, Button close, Slot, Arrow и Actions group (кнопки + ссылка).
В слот помещается что угодно: таблицы, графики, формы.
Arrow настраивается через пропс Direction: ↑ Top, → Right, ↓ Bottom, ← Left.
Stepper
Разделил на два вида: Simple и Step.

Simple — упрощённый, показывает прогресс, но переключение между шагами и управляется системой, а не пользователем. Имеет семантические цвета: Positive, Info, Warning, Negative, Neutral. Поддерживает переключение между маленькой точкой (пройденный этап) и большой (текущая позиция)
Step — навигационный степпер. Можно возвращаться к выполненным шагам, но двигаться вперёд нельзя до выполнения условий текущего этапа. Имеет слот для кастомного контента и настройку типов шагов: Done, Wait, Process, Error, Process-Error.
Оба вида работают горизонтально и вертикально.
Результаты
Появились единые принципы нейминга пропсов. Теперь дизайнеры говорят на одном языке и не нужно гадать, как называется нужный параметр. Запустили токены вместо стилей. Можно менять значения глобально. Всё это конечно было синхронизированно с разработкой.
Ни один продуктовый макет не сломался. Внешне компоненты остались прежними но внутри — новая архитектура.
Что это значило для меня
👌 Pixso не Figma 😆. Приходилось искать обходные пути. Разделение form-field на файлы — пример такого решения. Не идеально, но работает.
Хотелось сделать всё красиво с архитектурной точки зрения. Но реальность требовала компромиссов. Главное было не сломать работу команд и поэтому постоянно общался с продуктовыми дизайнерами. Собирал фидбек, объяснял решения и договаривался о сроках.
А параллельно с рефакторингом описывал логику работы, правила, ограничения. Это заняло почти столько же времени, сколько сама разработка. Но это совсем другая история, про которую я расскажу позже.