Хабр, привет! Меня зовут Алексей Афонин, я старший дизайнер продукта в Yandex Cloud. В прошлом году нам понадобилось полностью изменить внешний вид нашего сервиса для бизнес‑аналитики DataLens перед его выходом в опенсорс. Разработчики и дизайнеры интерфейсов часто сталкиваются с подобными задачами: есть уже работающий сервис, но его нужно стилизовать, например, в случае ребрендинга или при необходимости учесть специфический пользовательский опыт.
В наших продуктах мы пользуемся дизайн‑системой и библиотекой компонентов Gravity UI — это проект Yandex Cloud, который не так давно тоже вышел в опенсорс. В этой статье я поделюсь опытом, как мы решили задачу «перекрашивания DataLens» с её помощью. Но даже если вы не используете DataLens и ещё не знакомы с Gravity UI, наши наработки могут пригодиться командам разработчиков и дизайнеров, которые хотят стилизовать свои продукты быстрее и удобнее.
Зачем перекрашивать готовые сервисы
Когда приложение или веб‑сервис находятся на начальной стадии (условный MVP), то команда в большей степени фокусируется на полезных функциях. Но с развитием продукта вокруг него выстраивается всё более сильный бренд, появляется сообщество лояльных пользователей. Стилизация нужна для уникальной идентификации такого бренда, с которым у комьюнити уже выстроены доверительные отношения.
Какие трудности могут возникнуть на этом пути:
Однажды разработанный UI/UX может устареть. Мы все много раз наблюдали, как с развитием технологий пользовательские привычки менялись. Например, с появлением всё более удобных мобильных устройств у изначально ориентированных на десктоп сайтов появлялось всё больше мобильных пользователей. А когда‑то продуманные до мелочей веб‑интерфейсы — становились первыми кандидатами на ребрендинг.
В уже готовую экосистему захочется добавить новую функциональность на базе сторонней библиотеки. Это как раз наш пример с DataLens — поскольку этот сервис позволяет быстро визуализировать данные из самых разных источников, то с его помощью можно легко добавить визуальные элементы на сайт. Но если у сайта своя узнаваемая дизайн‑система, то важно, чтобы виджет или дашборд из DataLens был как бы частью сайта.
У продукта может появиться новая аудитория с новыми привычками. Сервис может выйти на новый рынок, где пользователи ведут себя совсем по‑другому. Например, предпочитают тёмную тему или пишут и читают не слева направо, а справа налево, и нуждаются в поддержке RTL в интерфейсе.
Во всех этих случаях важно, чтобы обновления интерфейса выглядели консистентно всей экосистеме продуктов и не нарушали привычных для пользователей паттернов работы. А самой команде важно, чтобы все изменения было легко внедрять и поддерживать, без утомительных ручных операций.
Что необходимо учесть при стилизации
При любой такой стилизации важно соблюдать несколько правил:
Учитывать контрастность при замене цвета. Она не должна сильно отличаться от принятых стандартов WCAG.
Оставлять прежними семантические цвета, например, сигнальные цвета состояния системы: красный — всё плохо, зелёный — хорошо.
Не рекомендуется менять свойства существующих компонентов (например, размеры).
Аккуратно менять цвет обводки, фона, и радиус скругления. Если ваша задача сделать сервис для повседневных задач, то не стоит сильно уходить от значений основных элементов. Так, в GravityUI все стили и цвета уже подобраны так, чтобы дизайн был «незаметным» для повседневного использования, чему могут мешать, например, явные тени или блюр.
Логотип лучше менять в пропорции 1:1. Не рекомендуется менять иконки, которые уже сделаны по стандартам. Если заменить иконки всё‑таки нужно, то важно соблюдать их формат и размерную сетку.
Что такое Gravity UI, какие возможности стилизации тут есть
Gravity UI содержит набор библиотек и компонентов для создания функциональных интерфейсов. Внешний вид компонентов гибко настраивается, и в Figma есть открытая компонентная библиотека дизайн-системы со своими константами. Я расскажу об основных.
Цвета
Gravity UI поддерживает работу с несколькими темами — есть светлая, тёмная и их версии с повышенным контрастом. Они основаны на двухслойной цветовой модели. Механизм темизации спроектирован для гибкой настройки цвета и поддержки айдентики брендов с разным набором требований.
Типографика
Система типографики состоит из стилей для наборного текста, для акцидентных заголовков и для кода (моноширинный шрифт). Можно использовать как шрифты по умолчанию, так и задать свои.
Радиусы скругления контролов
Одна из частей визуального стиля — радиусы скругления углов. В Gravity UI есть сет переменных для радиусов. Чтобы поменять радиусы в контролах, нужно изменить значения переменных.
В Gravity UI все правила и компоненты унифицированы, чтобы везде всё выглядело хорошо. Соответственно, стилизация в Gravity UI строится на изменении параметров переменных у перечисленных констант или компонентов. Всё, что нужно для стилизации, уже заложено в переменных — они специально вынесены отдельно, чтобы с ними можно было экспериментировать.
Есть несколько вещей, которые мы не стали выделять таким образом, — это проверенные решения, которые прекрасно работают с другими цветами и размерами. Но того набора опций у компонентов, которые вынесли отдельно, должно хватить для большинства задач.
Что дают возможности стилизации? При изменении параметра переменной цвет элемента с ней меняется во всём продукте. Например, вы сделали основной цвет красным. Теперь на всех страницах будут красные кнопки, красные обводки, а выделенный текст будет подсвечиваться светло‑красным цветом. При этом время разработчика или дизайнера сэкономлено, и не пришлось менять цвета вручную во всём сервисе.
Как стилизовали DataLens
Как мы уже рассказывали, DataLens развивался одновременно как cloud‑native‑решение для клиентов Yandex Cloud и как внутренний инструмент в Яндексе. В сентябре 2023-го этот сервис визуализации должен был выйти в опенсорс. DataLens как продукт для пользователей облака уже имел свою стилизацию, а перед нами стояла задача стилизовать два других: внутренний сервис DataLens YandexTeam и DataLens OpenSource, — чтобы эти продукты отличались от облачного сервиса. Расскажу по порядку, как мы это сделали.
Выбрали подход
В новых стилизациях нам всё равно было важно сохранить консистентность и узнаваемость облачного сервиса. Для этого мы взяли готовую группу так называемых бренд‑цветов. Что здесь имеется в виду? Всего у нас было около 100 CSS‑переменных цветов, и 15 из них относились к бренд‑группе: туда были включены те переменные, которые отвечают за кнопки, выделения, радиусы скругления — всё то, что в первую очередь влияет на восприятие бренда. Для облачных сервисов палитра этих элементов строилась вокруг синего. А с использованием дизайн‑системы нам нужно было поменять значения переменных в нескольких местах, чтобы получить нужный результат.
В коде Gravity UI не существует такой сущности как бренд‑группы, а цвета распределены по своим группам:
Text — группа переменных для цвета текста и иконок (тексты и иконки часто отображаются вместе, и есть смысл синхронизировать их внешний вид).
Base — группа цветов для всевозможных подложек, заливок и фонов.
Base Semantic — цвета подложек с окрасом Info, Positive, Warning, Danger, Misc. Предусмотрены значения как для Normal, так и для Hover‑стейтов. Могут подойти для некоторых типов инфографики, но не для всех. Группа выделена только в Figma. В коде это часть группы Base.
Base Float — цвета подложек элементов, находящихся над основным фоном страницы. Группа выделена только в Figma, в коде это часть группы Base.
Line — цвета обводок, линий, разделителей, рамок и любых других тонких элементов.
Effects — цвета для затемнения контента, теней и т. д.
Misc — группа с разными техническими цветами: для скроллбаров, осей графиков, фона тултипа в чарте. Подробнее о назначении каждой переменной можно прочитать в описании колорстилей в Figma или в Storybook.
С помощью Figma мы могли подобрать новые цвета и шрифты, а с помощью расширения Stylus переопределить переменные в браузере — то есть поддержать две новые темы для DataLens YandexTeam и OpenSource.
Нашли акцентный цвет
Сначала мы были в поисках акцентных бренд‑цветов для новых тем — это отличительный признак любого сервиса. Акцентный бренд‑цвет используют на кнопках, чекбоксах, свитчах, радио и других ключевых контролах компонентной библиотеки.
Акцентный цвет обеспечивает контраст и подчёркивает наиболее важные элементы в интерфейсах. Как правило, в процентном соотношении его меньше всего, но именно он самый главный, на его базе можно образовать альтернативные цвета. Обычно в акцентный цвет подкрашены кнопки подтверждения или создания. Кнопку с акцентным цветом нельзя не заметить.
Подобрали остальные цвета
Отталкиваясь от бренд‑цвета, изменяя тон, мы подобрали дополнительные цвета, которые используются в сервисе: цвета обводок, фонов и ссылок.
Как и в случае с основным синим цветом DataLens, мы искали тон по центру цветовой шкалы, чтобы для остальных цветов можно было подобрать разные по насыщенности оттенки.
Многие цвета мы оставили прежними. Например, не меняли цвета иконок, семантические цвета и тени. Обычно эти цвета выступают в роли нейтральных и сигнальных, поэтому их лучше сохранить в прежнем виде.
Проверили цвета на контрастность
Проверили на контрастность сочетания цвета текста на цвете фона — например, какое получается значение контрастности текста на фоне кнопок или цвет текста на фоне выбранных элементов в списке. Согласно стандарту WCAG, значение должно быть больше 4,5 contrast ratio. Это нужно для того, чтобы точно определить, будет ли на разных мониторах одинаково смотреться цвет текста или линии на другом цветном фоне.
Проверили цвета в двух темах
Выбирая цвета, мы проверяли их сразу в двух темах на ключевых экранах сервиса, где можно было проследить, как меняются цвета контролов, ссылок и логотипа.
Поработали с типографикой
Типографика в Gravity UI основана на использовании двух шрифтов и набора стилей, в которых указаны шрифт, вес, кегль и интерлиньяж.
Во внешнем и внутреннем DataLens используется собственный шрифт Yandex Cloud — YS text.
Для опенсорс‑версии мы по умолчанию использовали Inter для обычного набора и заголовков и Menlo в качестве моноширинного. Inter доступен в Google Fonts, а Menlo предустановлен по умолчанию в некоторых операционных системах. Эти шрифты всегда можно заменить теми, которые соответствуют брендбуку.
Правила для стилей типографики (заголовки, подзаголовки, наборный текст и подписи) оставили такими же, как в DataLens Yandex Cloud.
Покрасили логотип и заменили фавиконку
В основе логотипа сервиса лежит бренд‑цвет, который сочетается с остальными акцентными элементами сервиса.
Перекрасили иллюстрации
С помощью Figma перекрасили иллюстрации для статусов и отклика сервиса при взаимодействии с пользователями.
Главный цвет в иллюстрациях — акцентный бренд‑цвет, а все остальные цвета мы подбирали, как и с обводками и фонами выше — где‑то усиливается тон, где‑то уменьшается, где‑то используется чёрный или белый цвет.
В Yandex Cloud используются свои иллюстрации, не предназначенные для опенсорса. Для кастомизации опенсорса мы использовали готовую библиотеку с иллюстрациями.
Как для стилизации использовали расширение Stylus
С помощью Stylus мы переопределили переменные в браузере, используя базовый шаблон кода.
В редактор CSS вставили базовый шаблон:
{
@import url('https://fonts.googleapis.com/css2?family=Rubik&display=swap');
body.g-root {
--g-font-family-sans: 'Rubik', sans-serif;
}
.g-root_theme_light {
--g-color-base-brand: var(--g-color-private-orange-550-solid);
--g-color-base-brand-hover: var(--g-color-private-orange-650-solid);
--g-color-base-selection: var(--g-color-private-orange-150);
--g-color-base-selection-hover: var(--g-color-private-orange-300);
--g-color-text-link: var(--g-color-private-orange-600-solid);
--g-color-text-link-hover: var(--g-color-private-orange-750-solid);
--g-color-text-brand: var(--g-color-private-orange-600-solid);
--g-color-text-brand-heavy: var(--g-color-private-orange-750-solid);
--g-color-line-brand: var(--g-color-private-orange-600-solid);
}
.g-root_theme_dark {
--g-color-base-brand: var(--g-color-private-orange-550-solid);
--g-color-base-brand-hover: var(--g-color-private-orange-650-solid);
--g-color-base-selection: var(--g-color-private-orange-150);
--g-color-base-selection-hover: var(--g-color-private-orange-300);
--g-color-text-link: var(--g-color-private-orange-600-solid);
--g-color-text-link-hover: var(--g-color-private-orange-750-solid);
--g-color-text-brand: var(--g-color-private-orange-600-solid);
--g-color-text-brand-heavy: var(--g-color-private-orange-750-solid);
--g-color-line-brand: var(--g-color-private-orange-600-solid);
}
}
Теперь во вкладке сайта можно проверить изменения.
Переменные для быстрой кастомизации
Базовые переменные бренд-цветов
Название переменной |
За что отвечает |
---|---|
‑g-color‑base‑background |
Цвет фона страницы. Для светлой темы чаще всего используется белый, но можно использовать и любой другой. Для тёмной темы выбор более широкий — от нейтральных серых тонов до тёплых или холодных цветов |
‑g-color‑base‑brand |
Основной цвет бренда — фон для основной кнопки, чекбокса, радио, свитча, special‑темы у тултипа |
‑g-color‑base‑brand‑hover |
Ховер‑цвет для основного бренд‑цвета. Мы используем более тёмный оттенок, но допускается как более светлый, так и совсем другой цвет |
‑g-color‑base‑brand‑selection |
Подложки для элементов с семантикой «выбрано» |
‑g-color‑base‑brand‑selection‑hover |
Цвет ховера выбранных элементов. Не так часто используется в типовых задачах, как при подготовке всех стейтов для нового компонента или в прототипах |
‑g-color‑line‑brand |
Линии бренд‑цвета. Селектед‑стейт в карточках, табах; цвет спиннера |
‑g-color‑text‑brand |
Тексты бренд‑цвета при использовании без подложек |
‑g-color‑text‑brand‑heavy |
Тексты бренд‑цвета поверх подложек. Помогают скомпенсировать падение контраста от использования подложки |
‑g-color‑text‑brand‑contrast |
Контрастный цвет бренда. После того как определились с цветом основных контролов, нужно подобрать контрастный для него цвет. Контраст должен сохраняться во всех темах. Если цвет бренда принципиально не меняет яркость при переключении темы, можно попробовать цвета с постоянной яркостью: ‑g-color‑text‑light‑primary и ‑g-color‑text‑dark‑primary. Если цвет бренда меняет яркость, можно попробовать ‑g-color‑text‑primary или ‑g-color‑text‑inverted‑primary |
‑g-color‑text‑link |
Цвет ссылки |
‑g-color‑text‑link‑hover |
Цвет ховера для ссылки |
‑g-color‑text‑link‑visited |
Цвет посещённой ссылки |
‑g-color‑text‑link‑visited‑hover |
Цвет ховера посещённой ссылки |
‑gn‑aside‑header‑background‑color |
Цвет фоновой подложки в левой навигации под логотипом |
Отдельные переменные цветов
Название переменной |
За что отвечает |
‑ds‑color‑relation‑line |
Цвет линии связей в датасетах |
‑ds‑color‑avatar |
Дополнительный фон в датасетах |
‑w-local‑item‑border |
Граница в визарде у отдельной секции |
‑w-dataset‑item‑border‑hover |
Граница в датасетах по ховеру |
‑w-disabled‑item‑background |
Фон временно отключённой секции визуализации в визарде |
‑dl‑color‑base‑workbook‑icon |
Фон иконки сущности «воркбук» |
‑dl‑color‑entity‑chart‑wizard |
Фон иконки сущности «чарт визард» |
‑dl‑color‑entity‑chart‑ql |
Фон иконки сущности «чарт QL» |
‑dl‑color‑entity‑chart‑editor |
Фон иконки сущности «чарт эдитор» |
‑dl‑color‑entity‑connection |
Фон иконки сущности «подключение» |
‑dl‑color‑entity‑dataset |
Фон иконки сущности «датасет» |
‑dl‑color‑entity‑dashboard |
Фон иконки сущности «дашборд» |
Другие переменные цветов
С другими переменными цветов по группам можно ознакомиться в Storybook.
Светлая и тёмная тема
Для светлой темы используется этот класс:
.g-root_theme_light {
}
Для тёмной темы — этот:
.g-root_theme_dark {
}
Подключение шрифта
Подключать шрифт рекомендуем с помощью Google Fonts.
@import url('https://fonts.googleapis.com/css2?family=Interk&display=swap');
body.g-root {
--g-font-family-sans: 'Inter', sans-serif;
}
Стили шрифтов
Также можно заменить шрифты для отдельных переменных.
Название переменной |
За что отвечает |
---|---|
‑g-text‑body‑font‑family |
Стиль наборного текста |
‑g-text‑caption‑font‑family |
Стиль подписей |
‑g-text‑subheader‑font‑family |
Стиль подзаголовков |
‑g-text‑header‑font‑family |
Стиль заголовков |
‑g-text‑display‑font‑family |
Стиль дисплея (крупные заголовки) |
‑g-text‑code‑font‑family |
Стили для отображения кода и кода, встроенного в обычный наборный текст (inline‑стили) |
Варианты переменных шрифтов
С вариантами переменных можно ознакомиться в Storybook. Они отвечают за иерархию размеров.
Радиусы скругления
Данный набор переменных соответствует переменным в коде. Эти значения подставляются для контролов соответствующих размеров.
Название переменной |
За что отвечает |
---|---|
--g-border-radius-xs |
Скругления контролов XS |
--g-border-radius-s |
Скругления контролов S |
--g-border-radius-m |
Скругления контролов M (часто используемый контрол) |
--g-border-radius-l |
Скругления контролов L |
--g-border-radius-xl |
Скругления контролов XL |
Логотип, иконки и иллюстрации
Для продвинутой кастомизации можно заменить своим логотипом, иконками и иллюстрациями в формате SVG.
Для замены нужно сначала скрыть текущий объект, а затем вместо «Path» указать код SVG, сконвертированный через Base64:
.aside-header-logo-wrapper__logo-link .yc-button__icon-inner svg {
display:none;
}
.aside-header-logo-wrapper__logo-link .yc-button__icon-inner {
background: url("Path")
}
Для получения кода из SVG в поле Output Format нужно выбрать CSS Background Image.
Выводы
Благодаря возможности кастомизации мы из одного продукта сделали три разных по стилю. При этом везде используется одна кодовая база, что облегчает поддержку сервисов. У нас на это ушло до двух недель. А если бы мы разрабатывали новую стилистику сервисов с нуля, то потратили бы во много раз больше времени и сил.
Вот основные выводы, к которым мы пришли, работая над продуктом. Если захотите повторить наш путь, они будут вам полезны:
При стилизации с помощью Gravity UI лучше не отклоняться от подходов, которые описаны в этой дизайн‑системе. Они помогут сделать кастомизацию не только DataLens, но и любого другого сервиса, построенного на Gravity UI.
Кастомизировать так, чтобы приблизить дизайн интерфейса сервиса к дизайну вашего бренда. Мы рекомендуем буквально взять свой брендбук и сайт, поставить их рядом со стилизуемым сервисом и убедиться, что они однородны и целостны.
Надеюсь, наш опыт был полезен, буду рад в комментариях обсудить примеры ваших задач. А если вам интересен наш подход к дизайн‑системе, и хотелось бы работать в такой же парадигме — будем рады видеть вас в нашей команде. Примеры задач, которые мы решаем, можно посмотреть по ссылке в Notion.
Budarin
А если бы перед началом разработки изучили бы опыт Material Design - не пришлось бы сейчас мучаться подбирать и изобретать! :)
MD3 - просто песня с его инструментом по генерации и подбору цветов для светлой и темной теме по картинке, по брендовым и кастомным цветам
Alexeyafonin Автор
Добрый день. В статье описан опыт решения наших задач и более общий подход по подбору цветов для переменных, зашитых в дизайн-систему. В DataLens совсем недавно вышел инструмент для стилизации UI в платном тарифе, можно им воспользоваться для примерки цветов с его помощью.
Budarin
Вопрос не в конкретном инструменте, а в основных принципах дизайна ну отсюда вытекает естественный процесс генерации цветов.
Material Design - это не про конкретную библиотеку компонентов - это про дизайн и проектирование на его основе любых дизайн-систем и библиотек компонентов (там собраны лучшие идеи и практики дизайна интерфейсов)
Благодаря системному подходу в дизайне можно генерировать тысячи цветовых схем , которые будут консистентны и будут содержать контрастные цвета
Посмотрите на Хром - там есть галочка динамически менять цветовые темы - он по несколько раз за день меняет цветовые схемы - они генерируются динамически!
А так можно героически напрягаться и в конце месяца сгенерировать таки одну тему для продукта, руками подбирая цвета и даже потом какой-то инструмент изобрести, но это процесс от обратного
После такой работы если вы прочтете Material Desing вы будете удивлены : блин а почему мы раньше это не прочли? мы бы не мучались и сделали все гораздо проще!
Alexeyafonin Автор
В статье также учитываются практики, рассказывается с чем можно столкнуться, что есть от части внутри и как можно делать быстро и безопасно. Когда с этим работаешь, все происходит иначе – тут в этом речь. Вы говорите про волшебную кнопку, а мы про то, что под капотом.
Budarin
Вы говорите как вы героически сражались с тем что сотворили не используя знания и системный подход к проектированию UI - да вы молодцы поборолись со своими же проблемами и смогли таки создать тему
А я , пройдя такие же этапы разработки и лишь затем обнаруживший Material Design, рекомендую вам после всего этого процесса который вы прошли и которым идет большинство (не изучая теорию и лучшие практики бросаются что-то строить) изучить его - я думаю вы на многое взглянете другими глазами и узнаете что любую новую тему при системном подходе к проектированию UI не нужно героически создавать - она автоматически получается за пару секунд :) Думаю что после изучения Material Design у вас возникнет сильное желание переписать все сделанное ранее )
Alexeyafonin Автор
Мы все очень хорошо знакомы с material design, давайте опустим какие-то теории и начнем углубляться в практику, буду благодарен, если у вас получится привести реальный путь, как поменять стилистику в подобных сервисах, имея собственную дизайн-систему. Наверное будет польза.