От UI-кит до дизайн-системы
Опыт онлайн-кинотеатра ivi.
Когда в начале 2017 года мы впервые задумались о создании собственной системы доставки дизайна в код, об этом уже многие говорили, а кто-то даже делал.
Однако об опыте построения кроссплатформенных дизайн-систем и по сей день мало что известно, а понятных и проверенных рецептов, описывающих технологии и способы подобной трансформации процесса имплементации дизайна в уже работающий продукт, как не было, так и нет. Да и под «компонентами в коде» часто понимают очень разные вещи.
Меж тем компания год от года удваивала штат — нужно было масштабировать отдел дизайна и оптимизировать процессы создания и передачи макетов в разработку.
Умножаем всё это на «зоопарк» платформ, которые нужно поддерживать, и получаем подобие вавилонского столпотворения, которое просто не способно «нормально делать» и приносить доход.
Развитие платформ часто шло параллельно, и одна и та же функциональность могла выходить на разных платформах с лагом в несколько месяцев.
Мы начали с проблем, которые помогла бы решить дизайн-система, и сформулировали требования к её проектированию. Помимо создания единого визуального языка, увеличения скорости макетирования и разработки, повышения качества продукта в целом, было жизненно необходимо максимально унифицировать дизайн.
Это нужно для того, чтобы развитие функциональности стало возможным сразу на всех наших платформах одновременно: веб, iOS, Android, Smart TV, tvOS, Android TV, Windows 10, Xbox One, PS4, Roku — не прорабатывая при этом каждую из них в отдельности. И это у нас получилось!
Дизайн → данные
Когда принципиальные договорённости отделов продукта и разработки были достигнуты, мы сели за подбор технологического стека и проработку деталей всего процесса — от макета до релиза. Чтобы полностью автоматизировать процесс передачи дизайна в разработку, исследовали вариант с парсером параметров компонентов прямо из Sketch-файлов с макетами.
Оказалось, что находить нужные нам куски кода и извлекать нужные нам параметры — затея сложная и опасная. Во-первых, дизайнерам придётся быть крайне аккуратными в именовании всех слоёв исходника, во-вторых, это работает только для самых простых компонентов, а в-третьих, зависимость от чужой технологии и структуры кода исходного Sketch-макета ставит под угрозу будущее всего проекта.
Мы решили отказаться от автоматизации на этом участке. Так в команде дизайн-системы появился первый человек, на вход которому подаются дизайн-макеты, а на выходе — данные, описывающие все параметры компонентов, иерархически упорядоченные по методологии атомарного дизайна.
Дело оставалось за малым: где и как хранить данные, как передавать в разработку и как интерпретировать в разработке на всех поддерживаемых нами платформах. Вечер переставал быть томным…
Итогом регулярных встреч рабочей группы, состоящей из дизайнеров и тимлидов от каждой платформы, стала договорённость о нижеследующем.
Вручную разбираем визуал на элементы-атомы: шрифты, цвета, прозрачности, отступы, скругления, иконки, картинки и длительности для анимаций. И собираем из этого кнопки, инпуты, чек-боксы, виджеты банковских карт и так далее.
Стилям любого из уровней, кроме пиктограмм, присваиваем несемантические имена, например, названия городов, имена нимф, покемонов, марки автомобилей... Тут условие одно: список не должен исчерпаться раньше, чем закончатся стили — шоу маст гоу он! Семантикой же не стоит увлекаться, чтобы не пришлось добавлять среднюю кнопку между «small» и «medium», например.
Визуальный язык
Разработчики ушли думать, как хранить и передавать данные, чтобы это подходило всем платформам, а дизайну предстояло спроектировать элементы интерфейса, способные одинаково хорошо выглядеть и эффективно работать на всём парке поддерживаемых устройств.
Ранее мы уже успели «обкатать» большинство элементов дизайна в приложении под Windows 10, которое на тот момент было для нас новой платформой, то есть требовалась отрисовка и разработка «с нуля».
Рисуя его, мы смогли подготовить и проверить большинство компонентов и понять, какие из них должны были войти в будущую дизайн-систему ivi. Без такой «песочницы» подобный опыт можно было получить только большим числом итераций на уже работающих платформах, а на это потребовалось бы больше года.
Переиспользование одинаковых компонентов на разных платформах уменьшает количество макетов и массив данных дизайн-системы в разы. Поэтому дизайну предстояло решить ещё одну задачу, ранее не описанную в практиках продуктового дизайна и разработки, — как, например, кнопку для телефонов и планшетов переиспользовать на телевизорах? И как в принципе быть с размерами шрифтов и элементов на таких разных платформах?
Очевидно, требовалось спроектировать кроссплатформенную модульную сетку, которая будет задавать нужные нам размеры текста и элементов для каждой конкретной платформы. За точку отсчёта для сетки мы выбрали размер и количество постеров фильмов, которые хотим видеть на том или ином экране и, исходя из этого, сформулировали правило построения колонок сетки, при условии — ширина одной колонки равна ширине постера.
Теперь нужно привести к одному размеру макета все большие экраны и вписать их в общую сетку. Apple TV и Roku разрабатываются в размер 1920 x 1080, Android TV — 960 x 540, Smart TV в зависимости от вендора бывают такими же, а бывают 1280 x 720. Когда приложение рендерится и отображается на экранах Full HD, 960 умножается на 2, 1280 на 1,33, а 1920 выводится как есть.
Опуская скучные подробности, мы пришли к тому, что вообще все экраны, включая телеэкраны с точки зрения элементов и их размеров, покрываются одним дизайн-макетом, а все телеэкраны являются частным случаем общей кроссплатформенной сетки и состоят из пяти или шести колонок, как средний планшет или десктоп. Кому интересны подробности, го в комменты.
Теперь для отрисовки новой фичи нам не нужно рисовать макеты под каждую из платформ, плюс варианты адаптивности для каждой из них. Достаточно показать один макет и его адаптивность для всех платформ и устройств любой ширины: телефоны — 320–599, всё остальное — 600–1280.
Данные → разработка
Конечно, как бы нам ни хотелось прийти к абсолютно унифицированному дизайну, каждая платформа имеет свои уникальные особенности. Несмотря на то, что и веб, и Smart TV используют стек ReactJS + TypeScript, приложение для Smart TV запускается на устаревших WebKit- и Presto-клиентах, и потому не может использовать общие стили с вебом.
А email-рассылки и вовсе вынуждены работать с табличной вёрсткой. При этом ни одна из не-HTML-платформ не использует и не планирует использовать React Native или какие-то её аналоги, опасаясь ухудшения производительности, так как у нас слишком много кастомных лэйаутов, коллекций со сложной логикой обновления, изображений и видео.
Поэтому для нас не подходит распространённая схема — поставлять готовые CSS-стили или React-компоненты. Мы решили передавать данные в формате JSON, описывая значения в абстрактном декларативном виде.
Так свойство rounding: 8 приложение Windows 10 преобразует в CornerRadius="8", веб — в border-radius: 8px, Android — в android:radius="8dp", iOS — в self.layer.cornerRadius = 8.0.
Cвойство offsetTop: 12 один и тот же веб-клиент в разных случаях может интерпретировать как top, margin-top, padding-top или transform.
Декларативность описания также предполагает, что если платформа технически не может использовать какое-либо свойство или его значение, она может его проигнорировать. С точки зрения терминологии — мы сделали некое подобие языка эсперанто: что-то взяли из Android, что-то из SVG, что-то из CSS.
В случае, если на той или иной платформе потребуется отображать элементы как-то иначе, мы реализовали возможность передачи соответствующей генерации данных в виде отдельного JSON-файла.
Например, состояние «в фокусе» для Smart TV диктует изменение позиции текста под постером, значит — для этой платформы данный компонент в значении свойства «отступ» будет содержать необходимые ей 8 поинтов отступа.
Хоть это и усложняет инфраструктуру дизайн-системы, зато даёт дополнительную степень свободы, оставляя нам возможность самим управлять визуальной «непохожестью» платформ, а не быть заложниками нами же созданной архитектуры.
Пиктограммы
Иконографика в цифровом продукте — это всегда объёмный и не самый простой подпроект, часто имеющий отдельного дизайнера. Глифов всегда много, каждый из них имеет несколько размеров и цветов, к тому же платформам они нужны, как правило, в разных форматах. В общем, не было повода не завести всё это в дизайн-систему.
Глифы загружаются в векторном SVG-формате, а значения цветов автоматически заменяются переменными. Приложения-клиенты могут получать их уже готовыми к использованию — в любом формате и цвете.
Предпросмотр
Поверх JSON’а с данными мы написали инструмент для предпросмотра компонентов — JS-приложение, на лету пропускающее JSON-данные через свои генераторы разметки и стилей, и отображающее в браузере различные вариации каждого из компонентов. Предпросмотр является точно таким же клиентом, как и платформенные приложения, и работает с теми же данными.
Понять, как работает тот или иной компонент, проще всего путём взаимодействия с ним. Поэтому мы не стали использовать инструменты, подобные Storybook, а сделали интерактивный предпросмотр — можно пощупать, понаводить, покликать…
При добавлении в дизайн-систему нового компонента — он появляется в предпросмотре, чтобы платформам было на что ориентироваться при его внедрении.
Документация
На основе тех данных, которые в виде JSON поставляются платформам, автоматически формируется документация по компонентам. Описывается перечень свойств и возможные типы значений в каждом из них.
После автогенерации информацию можно уточнить в ручном режиме, добавить текстовое описание. Предпросмотр и документация снабжены перекрёстными ссылками друг на друга на уровне каждого компонента, а вся информация, попадающая в документацию, доступна разработчикам в виде дополнительных JSON-файлов.
Депрекатор
Ещё одной необходимостью стала возможность со временем заменять и обновлять уже существующие компоненты. Дизайн-система научилась сообщать разработчикам, какие свойства или даже целые компоненты использовать нельзя и удалять их, как только они перестают использоваться на всех платформах. Пока в этом процессе ещё много «ручного» труда, но мы не стоим на месте.
Клиентская разработка
Несомненно, самым масштабным по сложности этапом стала интерпретация данных дизайн-системы в коде всех поддерживаемых нами платформ. Если, например, модульные сетки на вебе не являются чем-то новым, то разработчики нативных мобильных приложений под iOS и Android изрядно попотели, прежде чем придумали, как с этим жить.
Для верстки экранов iOS-приложения мы используем два базовых механизма, которые предоставляет iviUIKit: cвободная компоновка элементов и компоновка коллекций элементов. Мы используем VIPER, и всё взаимодействие с iviUIKit сосредоточено во View, а большая часть взаимодействия с Apple UIKit сосредоточена в iviUIKit.
Размеры и расположение элементов задаются в терминах колонок и синтаксических конструкций, работающих поверх нативных констрейнтов iOS SDK, делающих их более прикладными. Особенно это упростило нам жизнь при работе с UICollectionView.
Мы написали несколько настраиваемых обёрток для лэйаутов, в том числе довольно сложных. Клиентского кода получилось минимум, он стал декларативным.
Для генерации стилей в проекте Android мы используем Gradle, превращая данные дизайн-системы в стили формата XML. При этом у нас есть несколько генераторов различного уровня:
- Базовые. Парсят данные примитивов для генераторов более высокого уровня.
- Ресурсные. Скачивают картинки, иконки и прочую графику.
- Компонентные. Пишутся для каждого компонента, где описано какие свойства и как перевести в стили.
Релизы приложений
После того, как дизайнеры нарисовали новый компонент или переработали существующий, эти изменения попадают в дизайн-систему. Разработчики каждой из платформ дорабатывают свою кодогенерацию, обеспечивая поддержку изменений.
После этого его можно использовать в реализации новой функциональность, где этот компонент необходим. Таким образом, взаимодействие с дизайн-системой происходит не в реальном времени, а только в момент сборки новых релизов.
Такой подход также позволяет лучше контролировать процесс передачи данных и гарантирует работоспособность кода в проектах клиентской разработки.
Итоги
Скоро год как дизайн-система стала частью инфраструктуры, обслуживающей развитие онлайн-кинотеатра ivi, уже можно делать кое-какие выводы:
- Это большой и сложный в реализации проект, требующий постоянных выделенных ресурсов.
- Это позволило нам создать свой уникальный кроссплатформенный визуальный язык, отвечающий задачам сервиса онлайн-видео.
- У нас больше нет визуально и функционально отстающих платформ.
Предпросмотр компонентов дизайн-системы ivi — design.ivi.ru.