Наследуемые свойства в SDUI платформе ВкусВилл. Часть 1: Контекст

Наследуемые свойства в SDUI платформе ВкусВилл. Часть 1: Контекст

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

О том, как применить подобный подход к цветовой семантике без SDUI на примере текущего приложения “ВкусВилл”, я писал в своем телеграм-канале.

Зачем нужны наследуемые свойства

Чтобы ответить на этот вопрос, нужно сначала разобраться, что такое SDUI. SDUI (Server Driven User Interface) - это концепция пользовательского интерфейса, управляемого сервером. Основная часть этой концепции относится не столько к дизайну, сколько к работе с данными и обработке действий пользователя. В традиционных приложениях вся обработка происходит на стороне клиента, включая большую часть бизнес-логики.

В SDUI-приложении клиент настолько “тупой”, что виджетам остается только отправлять события на сервер (например, “На меня нажали”) и ждать от него инструкций о том, как должен измениться интерфейс после этого действия. Вся бизнес-логика в этом случае выносится на серверную сторону.

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

Наследуемые свойства в SDUI платформе ВкусВилл. Часть 1: Контекст

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

Контракт

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

Возьмем простой контракт из консервативного SDUI-приложения: кнопка с иконкой будет выглядеть следующим образом:

Наследуемые свойства в SDUI платформе ВкусВилл. Часть 1: Контекст

В целом, все достаточно компактно и понятно. Но что, если мы захотим изменить кнопку, изменить ее внешний вид и содержание? Нам придется охватить все параметры и, конечно же, выпустить новую версию приложения в магазинах. Мы же хотим избежать этого как можно дольше. Если мы возьмем, к примеру, JSON-макет простой страницы в Figma, а файлы Figma, как ни странно, в формате JSON, там будет более 800 тысяч строк 🤯.

Наследуемые свойства в SDUI платформе ВкусВилл. Часть 1: Контекст

Так насколько же наследуемые стили позволяют сократить размер контракта? Тот же экран, но уже оптимизированный под нашу платформу в формате JSON имеет всего около 1200 строк. Примерно так выглядит кнопка с иконкой и текстом в этом формате:

Наследуемые свойства в SDUI платформе ВкусВилл. Часть 1: Контекст

Значительно больше строк, чем в первом примере, но все еще читаемо, и внутри может быть все, что угодно. Мы не ограничены заранее определенными параметрами виджета кнопки. Таким образом нам удалось достичь вариативности макета как в Figma и в то же время существенно оптимизировать данные дерева объектов и их параметры.

Контекст (микротема)

Обычная структура семантического токена цвета в теме примерно следующая:

light-theme. background-brand-accent

Иногда к этому добавляется еще уровень токенов компонентов. Все имя токена полностью “лежит” в каком-либо параметре, например “button-background”. Цвет текста отдельно в свойствах “icon-color” и “label-color”, что-то вроде light-theme.text-color-on-accent.

В результате получаем зеленую кнопку.

Наследуемые свойства в SDUI платформе ВкусВилл. Часть 1: Контекст

Но контекст добавляет к этой картине новое измерение

<i>структура имени токена цвета в платформе Манго.</i>
структура имени токена цвета в платформе Манго.

За цвет в такой системе отвечают два свойства: одно для токена цвета и одно для его контекста. Значение контекста указывается в свойстве “context”, а в самом токене указывается только цвет. Например, в свойстве background указывается значение “primary”, а в свойствах text-color и icon-color указывается значение “on-primary”. По умолчанию значение свойства context равно “inherit”. Это означает, что виджет наследует значение контекста от родительского виджета. Если мы хотим, чтобы кнопка была зеленой, мы должны установить значение контекста на “green-accent”.

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

<i>нейтральный контекст</i>
нейтральный контекст
<i>пример групп контекстов</i>
пример групп контекстов

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

<i>пример смены контекста для виджета тизера товара</i>
пример смены контекста для виджета тизера товара

Как видно из приведенного выше примера, кнопка "В корзину" не меняет свой цвет, потому что у нее задан определенный контекст “green-accent”, а не “inherit”, и поэтому она не наследует контекст от своего родительского виджета.

Контексты в фигме

В коде с такими сложными механиками более менее все понятно, но как это реализовать в Figma? К сожалению, идеального решения не существует, даже с использованием новых variables. Сейчас у нас цвета на стилях, и даже если перейти на переменные, то без тарифа Enterprise картина кардинально не изменится. Теоретически, можно было бы попытаться создать mode для каждого контекста и разные коллекции для разных тем. Возможно, это сработало бы, но это очень затратно. Кроме того, в нашей платформе виджеты автоматически выгружаются на фронтенд, а это значит, что параметр также необходимо передавать.

Контекст для автоматики хранится в специальном служебном слое в свойстве компонента.
Контекст для автоматики хранится в специальном служебном слое в свойстве компонента.

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

1212
11
3 комментария

Очень интересно, пиши ещё.

1

Как жаль, что реализация этого не соответствует красоте описанного

Ход разработки активно освещается на моём канале в телеграме
https://t.me/uxflow, там же вы можете почитать о реализации и составить себе более полное представление