- PVSM.RU - https://www.pvsm.ru -
Термином «дизайн-система» в IT давно никого не удивишь. Компании систематизируют дизайн продуктов, придумывая свои или используя чужие инструменты для управления стилями, паттернами и компонентами.
Badoo не является исключением: с помощью нашей дизайн-системы Cosmos мы поддерживаем общие принципы дизайна для четырёх приложений, работающих на четырёх платформах.

Одна из первых и основных вещей, с которой начинается работа по созданию дизайн-системы, — это токены (или переменные), которые определяют значения разных сущностей системы.
Как это работает? Например, у вас есть приложение для двух платформ. Вместо того чтобы для каждой заново указывать в CSS-файле размер и стиль шрифтов, вы можете хранить эти значения в JSON-файле, который легко преобразуется в код для любой платформы. В дальнейшем этот файл можно использовать и в других проектах с другими кодовыми базами.
Несмотря на потенциал дизайн-токенов, во многих компаниях их структура остаётся довольно простой, что сильно ограничивает возможности их применения.
Я хочу поделиться адаптированным переводом статьи моего коллеги Кристиано Растелли (Cristiano Rastelli [1]), который несколько лет развивает дизайн-систему Cosmos. На примере своего опыта он показывает, как работать с токенами более эффективно: добавлять метаданные и использовать их для описания свойств компонентов.
Под катом — небольшой рассказ о том, как выглядят дизайн-токены в Badoo и почему они значительно упрощают процесс разработки.
В последние месяцы я не мог не заметить, как много людей (и компаний) подразумевают под дизайн-токенами только цвет, типографику и интервалы, а в некоторых случаях — тайминг, размеры и возвышение (elevation [2]).
Они упускают главное: дизайн-токены могут быть чем-то большим, чем всё перечисленное.
В этой статье я поделюсь своим мнением и опытом по теме и покажу, что и как можно сделать с помощью токенов.
Как я уже говорил, многие считают дизайн-токены «набором ключевых свойств дизайна приложения или сайта». Это простое определение часто вводит в заблуждение и ограничивает возможности применения токенов.
Например, взгляните на эту песочницу: Design System Playground [3]. Всё, что создатели предлагают менять в ней, — это цвета и типографика.
Попробуйте этот инструмент для управления [4] дизайн-токенами — и вы увидите, что он тоже основан на идее «ключевых» значений свойств дизайна:

Скриншот интерфейса, который используется для добавления нового дизайн-токена на сайте designtokens.dev
Посмотрите, сколько плагинов для экспорта дизайн-токенов создано для Figma, Sketch и Framer. В основе каждого из них лежит идея экспорта гранулированных и изолированных значений цветов, размера шрифтов и высоты строк, интервалов и т. д.
Изучите разделы про дизайн-токены на сайтах разных дизайн-систем [5]: в большинстве случаев там будет написано лишь про цвета, типографику, интервалы, возвышение, тайминг, размеры и прочее.
Хочу уточнить: в этом нет ничего плохого. Но, как я сказал выше, я считаю, что дизайн-токены способны на большее.
По моему опыту, огромный потенциал и сила дизайн-токенов проявляются в полной мере тогда, когда они:
Нет причин не использовать дизайн-токены для описания свойств компонентов.
С технической точки зрения дизайн-токены являются упорядоченными списками пар «ключ — значение», которые описывают дизайнерские решения. То, какими правилами и ограничениями мы будем руководствоваться при описании через них интерфейса, — лишь вопрос удобства (и контекста).
В некоторых случаях (особенно когда дизайн-система находится на ранней стадии развития) целесообразно ограничиться ключевыми значениями (цветами, типографикой, интервалами). Но когда система усложняется, когда в неё добавляется всё больше и больше компонентов, то хорошо бы использовать дизайн-токены и для них.
Более того, основные цвета и шрифты меняются нечасто (например, при ребрендинге), а вот компоненты, по моему опыту, развиваются непрерывно. Например, в нашу дизайн-систему в последние месяцы было добавлено много новых компонентов. Некоторые из имеющихся были усовершенствованы, а какие-то — даже отрефакторены. Несколько компонентов были расширены с целью использования их в других контекстах или визуальных состояниях. И лишь пара цветов и один шрифт были изменены.
Каждый раз при создании компонента мы обсуждаем с дизайнерами или разработчиками, которые работают над дизайн-системой, возможные состояния и варианты компонента, а также его дизайнерские решения. И затем переводим все эти спецификации в конкретные дизайн-токены.

Пример набора дизайн-токенов для компонента (Lifestyle Badge)
Вот так, к примеру, выглядит JSON-файл для компонента Lifestyle Badge (для управления токенами мы используем Style Dictionary [6]):
{
"lifestylebadge": {
"height": {
"value": "34",
"type": "size"
},
"border_radius": {
"value": "17",
"type": "size"
},
"padding": {
"start": {
"value": "{spacing.md.value}",
"type": "size"
},
"end": {
"value": "{spacing.md.value}",
"type": "size"
}
},
"icon_size": {
"value": "{icon.size.md.value}",
"type": "size"
},
"spacing_icon_text": {
"value": "{spacing.xsm.value}",
"type": "size"
},
"base": {
"text_color": {
"value": "{color.gray_dark.value}",
"type": "color"
},
"background_color": {
"value": "{color.gray_light.value}",
"type": "color"
}
},
"selected": {
"text_color": {
"value": "{color.white.value}",
"type": "color"
},
"background_color": {
"value": "{color.primary.value}",
"type": "color"
}
}
}
}
Эти значения преобразуются в разные форматы и распределяются по различным платформам (мобильный веб, iOS, Android) и продуктам (сейчас мы поддерживаем четыре основных бренда и несколько немарочных (white label brands)).
Как только токены для компонента добавляются в систему, разработчики, которые над ним работают, получают все необходимые дизайн-спецификации:

Так выглядят токены Lifestyle Badge под Android в нашей дизайн-системе
На первый взгляд подход выглядит нерациональным и усложняющим систему. Но мы убедились в том, что это позволяет нам распределять информацию по «потребителям» — разработчикам — надёжным и отлаженным способом, что уменьшает вероятность возникновения путаницы, недопонимания и человеческих ошибок.
Со временем разработчики начинают требовать наличия конкретных токенов при добавлении компонентов в систему. В этом случае отпадает необходимость открывать Sketch-файл (или страницу в Sympli) и выяснять размеры, цвета и спецификации компонентов. Вместо этого им достаточно обновить в своих кодовых базах версию пакета дизайн-токенов и запустить скрипт синхронизации/обновления, после чего они автоматически получат все спецификации, представленные в виде легкочитаемых имён переменных.
Также мы с помощью иллюстраций показываем, как и где определены и используются дизайн-токены компонентов.

Пример набора дизайн-токенов для другого компонента (Action Sheet). С их помощью можно выразить даже выравнивание по вертикальной оси (gravity)!
Ещё один важный аспект такого подхода заключается в том, что вы получаете все те же преимущества, что и при использовании токенов для базовых свойств дизайна.
Если рассматривать дизайн-токены в качестве способа передачи информации, то разумно использовать их и для компонентов.
Оба основных инструмента управления дизайн-токенами (Theo [8] и Style Dictionary [6]) поддерживают добавление метаданных к паре «ключ — значение». Их можно использовать для добавления комментариев и аннотаций, однако по-настоящему сила метаданных раскрывается тогда, когда их используют для создания дополнительного смыслового слоя.
Например, вы можете добавить информацию о типе значений, чтобы использовать её позднее, например при обработке значений для получения конкретных результатов. Вы можете добавить информацию о группировке, чтобы потом с её помощью организовать или отфильтровать значения так, как вам нужно. Можно добавлять самые разные виды информации в зависимости от контекста и потребностей. То есть вы добавляете то, что релевантно для вас, вашего контекста, способа применения токенов и задач.
Первой метаинформацией, которую мы добавили после внедрения дизайн-токенов в нашу дизайн-систему [9], стала «документация/комментарий» («documentation/comment»). С её помощью мы ввели в токен дополнительные данные, которые будут отображаться на сайте дизайн-системы. Мы применили пространство имён documentation, а не просто свойство comment, на тот случай, если нам понадобится добавить больше информации: к примеру, если дизайн-токен устареет и нужно будет описать его замену.
Вот пример добавления комментария в дизайн-токен:
{
"actionsheet": {
…
"item": {
"height": {
"value": "48",
"type": "size",
"documentation": {
"comment": "Notice: this is the 'internal' size, the border will be added as extra"
}
},
…
}
}
}
А так выглядит документация этого токена:

Сразу после этого мы добавили второй вид метаинформации — «тип» ("type"). Это скорее семантическое понятие, а не программистское.
Вот примеры типов, которые мы используем:
{
"color": {
"primary": {
"value": "{color.palette.purple_grape.value}",
"type": "color"
}
},
"icon": {
"size": {
"xsm": {
"value": "10",
"type": "size"
}
}
},
"tooltip": {
"shadow": {
"opacity": {
"value": "0.08",
"type": "opacity"
}
},
"animation": {
"timing_bounce": {
"value": "0.9",
"type": "time",
"unit": "s"
}
}
},
"chat": {
"bubble": {
"relative_width": {
"value": "0.8",
"type": "ratio"
}
}
},
"actionsheet": {
"gravity": {
"value": "center",
"type": "string"
}
}
}
Метаданные «тип» используются в скриптах постобработки для генерирования конкретных результатов для разных платформ. Вот фрагмент кода шаблона, который используется для генерирования XML-файла под Android:

В зависимости от «типа» токена мы генерируем значения с форматированием, необходимым для Android
А это отформатированный под наши требования результат:

Сгенерированный под Android XML-файл с соответствующим форматом/типом, который зависит от метазначения "type" в токене
Позднее мы добавили третий вид метаданных: «группа» ("group"). Это важнейший вид метаинформации, который используется по многим причинам.
Для некоторых продуктов и задач нам нужно создавать подмножества токенов (например, только цвета). Для этого мы добавили в словарь стилей конкретный фильтр [10]:

Скрипт для фильтрации «правильных» цветов
Вы могли заметить, что здесь мы используем два условия: одно для выбора токенов по типу «цвет» ("color"), второе — для отсеивания любых «псевдонимов» ("alias"). Это сделано потому, что мы используем специальные вспомогательные промежуточные цвета (вроде color-palette-purple-grave) в качестве указателей на их шестнадцатеричные значения, но поскольку они не нужны нам в виде сгенерированных токенов, мы отмечаем их флагом isAlias.
Затем этот фильтр используется для генерирования файлов только с цветами:

Мы фильтруем дизайн-токены в зависимости от метаданных "type", чтобы сгенерировать файлы только с цветами
Это лишь один пример того, как с помощью метаданных можно фильтровать токены и генерировать конкретные файлы. Можно придумать много других способов применения в зависимости от ваших потребностей и контекста.
Ещё один способ использования метаданных — группировка дизайн-токенов по определённым правилам.
Например, с помощью атрибута «группа» ("group") можно создавать списки токенов, относящихся к одной группе, а затем использовать эти списки (или ассоциативные массивы) в кодовой базе.
Сгруппируем дизайн-токены по группам в зависимости от значений цветов и размеров иконок:
// color/xxx.json
{
"color": {
"primary": {
"value": "{color.palette.purple_grape.value}",
"type": "color",
"group": "brand"
},
…
"generic_red": {
"value": "{color.palette.pink_salmon.value}",
"type": "color",
"group": "generic"
},
…
"gray_dark": {
"value": "#767676",
"type": "color",
"group": "mono"
},
"feature": {
"verification": {
"value": "{color.palette.blue_neon.value}",
"type": "color",
"group": "features"
},
…
},
"provider": {
facebook": {
"value": "#4867aa",
"type": "color",
"group": "providers"
},
…
},
"others": {
error": {
"value": "{color.generic_red.value}",
"type": "color",
"group": "others"
},
…
}
}
}
// icon.json
{
"icon": {
"size": {
"xsm": {
"value": "10",
"type": "size",
"group": "size"
},
"sm": {
"value": "16",
"type": "size",
"group": "size"
},
"md": {
"value": "22",
"type": "size",
"group": "size"
},
"lg": {
"value": "30",
"type": "size",
"group": "size"
},
"xlg": {
"value": "36",
"type": "size",
"group": "size"
},
"xxlg": {
"value": "46",
"type": "size",
"group": "size"
}
},
"jumbo-size": {
"sm": {
"value": "{brick.size.sm.value}",
"type": "size",
"group": "size"
},
"md": {
"value": "{brick.size.md.value}",
"type": "size",
"group": "size"
},
"lg": {
"value": "{brick.size.lg.value}",
"type": "size",
"group": "size"
}
}
}
}
// spacing.json
{
"spacing": {
"xsm": {
"value": "4",
"type": "size",
"group": "size"
},
"sm": {
"value": "8",
"type": "size",
"group": "size"
},
"md": {
"value": "12",
"type": "size",
"group": "size"
},
"lg": {
"value": "16",
"type": "size",
"group": "size"
},
"xlg": {
"value": "24",
"type": "size",
"group": "size"
},
"xxlg": {
"value": "32",
"type": "size",
"group": "size"
},
"gap": {
"value": "{spacing.lg.value}",
"type": "size",
"group": "size"
}
}
}
Можно сгенерировать ассоциативные массивы в Sass (они же Sass maps, или карты):
$tokens-color-map: (
providers: (
provider-facebook: $token-color-provider-facebook,
…
),
mono: (
black: $token-color-black,
gray-dark: $token-color-gray-dark,
gray: $token-color-gray,
gray-light: $token-color-gray-light,
white: $token-color-white
),
others: (
error: $token-color-error,
…
),
brand: (
primary: $token-color-primary,
…
),
generic: (
generic-red: $token-color-generic-red,
…
),
features: (
…
feature-verification: $token-color-feature-verification
),
);
$tokens-icon-map: (
size: (
size-xsm: $token-icon-size-xsm,
size-sm: $token-icon-size-sm,
size-md: $token-icon-size-md,
size-lg: $token-icon-size-lg,
size-xlg: $token-icon-size-xlg,
size-xxlg: $token-icon-size-xxlg,
jumbo-size-sm: $token-icon-jumbo-size-sm,
jumbo-size-md: $token-icon-jumbo-size-md,
jumbo-size-lg: $token-icon-jumbo-size-lg
),
);
$tokens-spacing-map: (
size: (
xsm: $token-spacing-xsm,
sm: $token-spacing-sm,
md: $token-spacing-md,
lg: $token-spacing-lg,
xlg: $token-spacing-xlg,
xxlg: $token-spacing-xxlg,
gap: $token-spacing-gap
),
);
...
Теперь эти карты позволят нам объявлять подобные конструкции:


Использование в нашей кодовой базе Sass-карт, сгенерированных дизайн-токенами
Таким образом, мы не просто абстрагируемся от объявления списков классов/свойств в зависимости от цвета, размера и прочих параметров — для нас гораздо важнее то, что у разных продуктов могут быть разные списки цветов, интервалов, размеров иконок и т. д., и при этом один и тот же Sass-код теперь работает для любых списков цветов, интервалов, размеров и прочего.
Эти Sass-файлы являются универсальными и могут использоваться для компонентов разных продуктов и на разных платформах.
При добавлении или удалении цвета список обновляется автоматически. Не нужно менять код на уровне компонента или приложения. Всё управляется с помощью объявлений дизайн-токенов.
Это работает не только для CSS/Sass. Те же преимущества списков токенов, относящихся к одной группе, можно получить и в JavaScript:

На сайте дизайн-системы мы демонстрируем все возможные цвета компонентов, используя списки токенов, сгенерированные через ассоциированные с ними метаданные "group"
Это приводит нас ещё к одному способу применения — CSS-в-JS. В этом случае список возможных цветов (отступов, размеров) для компонентов становится просто циклом/картой списка объектов «ключ — значение», сгенерированным инструментом для работы с дизайн-токенами.
В рамках этого же подхода мы недавно использовали свойство "group" для генерирования TypeScript-определений. С помощью специального шаблона в словаре стилей [11] мы можем генерировать такие файлы:
declare namespace Tokens {
namespace Color {
enum Providers {
PROVIDER_FACEBOOK = 'provider-facebook',
…
}
enum Mono {
BLACK = 'black',
GRAY_DARK = 'gray-dark',
GRAY = 'gray',
GRAY_LIGHT = 'gray-light',
WHITE = 'white'
}
enum Others {
ERROR = 'error',
…
}
enum Brand {
PRIMARY = 'primary',
…
}
enum Generic {
GENERIC_RED = 'generic-red',
…
}
enum Features {
…
FEATURE_VERIFICATION = 'feature-verification'
}
type Color = Providers | Mono | Others | Brand | Generic | Features;
}
namespace Icon {
enum Size {
XSM = 'xsm',
SM = 'sm',
MD = 'md',
LG = 'lg',
XLG = 'xlg',
XXLG = 'xxlg',
JUMBO_SM = 'jumbo-sm',
JUMBO_MD = 'jumbo-md',
JUMBO_LG = 'jumbo-lg'
}
}
namespace Spacing {
enum Size {
XSM = 'xsm',
SM = 'sm',
MD = 'md',
LG = 'lg',
XLG = 'xlg',
XXLG = 'xxlg',
GAP = 'gap'
}
}
}
export default Tokens;
Эти TypeScript-определения и перечисления позднее могут напрямую использоваться клиентскими кодовыми базами для обеспечения строгой типобезопасности (и автоматически заполняться в IDE).
В качестве ещё одного возможного использования метаданных для добавления в дизайн-токены дополнительного семантического значения, в частности взаимосвязей, можно упомянуть объявление текстовых стилей. Все мы знаем, что для создания минимально жизнеспособного текстового стиля нужно задать не меньше четырёх параметров: font-family, font-size, line-height и font-weight.
Как определить и явно объявить взаимосвязи между отдельными дизайн-токенами, чтобы создать «текстовый стиль H1»? Можно отразить это в наименованиях, чтобы все свойства одного стиля имели одинаковый префикс или суффикс. Тогда почему бы не использовать метаданные, ассоциированные с токенами, для их идентификации и фильтрации/группировки в ходе обработки?
Нам это реализовывать не нужно, но если бы потребовалось, то я однозначно воспользовался бы атрибутом метаданных, ассоциированным с разными значениями стилей.
Основные выводы:
Например, с помощью метаданных можно:
Я показал, как мы реализуем этот подход в нашей дизайн-системе. Но мы используем дизайн-токены для удовлетворения наших потребностей. Уверен, что у вас есть (или вы найдёте) множество других примеров того, как можно использовать дизайн-токены, помимо цветов, типографики и интервалов.
Всё ограничивается лишь воображением. Подумайте о том, что вы можете сделать, если добавите в токены метаинформацию, имеющую для вас конкретное значение в зависимости от того, как и где эти токены используются.
А потом обязательно расскажите об этом сообществу!
P. S. Больше о том, что такое дизайн-токены, можно узнать из онлайн-курса [12] и выступления [13] Джины Энн [14], публикации [15] Дэнни Бэнкса [16], репозитория [17] Стюарта Робсона [18] и статьи [19] Робина Рендла [20]. Есть ещё репозиторий рабочей группы W3C [21], в который можно внести свой вклад. Чтобы получить более полное представление о том, как в Badoo используются дизайн-токены, почитайте эту статью: How to manage your Design Tokens with Style Dictionary [22].
Автор: Дмитрий Кузнецов
Источник [23]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/interfejsy/349330
Ссылки в тексте:
[1] Cristiano Rastelli: https://twitter.com/areaweb
[2] elevation: https://material.io/design/environment/elevation.html#
[3] Design System Playground: https://design-system-playground.netlify.com/
[4] этот инструмент для управления: https://www.designtokens.dev/
[5] разных дизайн-систем: https://adele.uxpin.com/
[6] Style Dictionary: https://amzn.github.io/style-dictionary/#/
[7] дизайн-системах: https://medium.com/@didoo/how-to-manage-your-design-tokens-with-style-dictionary-98c795b938aa
[8] Theo: https://github.com/salesforce-ux/theo
[9] нашу дизайн-систему: https://badootech.badoo.com/from-zero-to-cosmos-part-1-2d080fe35bf2
[10] словарь стилей конкретный фильтр: https://amzn.github.io/style-dictionary/#/api?id=registerfilter
[11] специального шаблона в словаре стилей: https://amzn.github.io/style-dictionary/#/api?id=registertemplate
[12] онлайн-курса: https://aycl.uie.com/virtual_seminars/design_tokens_scaling_design_with_a_single_source_of_truth
[13] выступления: https://www.youtube.com/watch?v=wDBEc3dJJV8
[14] Джины Энн: https://medium.com/@jina
[15] публикации: https://dbanks.design/blog/documenting-design-tokens/
[16] Дэнни Бэнкса: https://medium.com/@dbanksdesign
[17] репозитория: https://github.com/sturobson/Awesome-Design-Tokens
[18] Стюарта Робсона: https://medium.com/@sturobson
[19] статьи: https://css-tricks.com/what-are-design-tokens/
[20] Робина Рендла: https://medium.com/@robinrendle
[21] рабочей группы W3C: https://github.com/design-tokens/community-group
[22] How to manage your Design Tokens with Style Dictionary: https://medium.com/@didoo/how-to-manage-your-design-tokens-with-style-dictionary-98c795b938aa?source=post_page-----ad7c98f4f228----------------------
[23] Источник: https://habr.com/ru/post/491948/?utm_source=habrahabr&utm_medium=rss&utm_campaign=491948
Нажмите здесь для печати.