Хабр, привет! Меня зовут Алексей Афонин, я старший дизайнер продукта в Yandex Cloud. В прошлом году нам понадобилось полностью изменить внешний вид нашего сервиса для бизнес‑аналитики DataLens перед его выходом в опенсорс. Разработчики и дизайнеры интерфейсов часто сталкиваются с подобными задачами: есть уже работающий сервис, но его нужно стилизовать, например, в случае ребрендинга или при необходимости учесть специфический пользовательский опыт.

В наших продуктах мы пользуемся дизайн‑системой и библиотекой компонентов Gravity UI — это проект Yandex Cloud, который не так давно тоже вышел в опенсорс. В этой статье я поделюсь опытом, как мы решили задачу «перекрашивания DataLens» с её помощью. Но даже если вы не используете DataLens и ещё не знакомы с Gravity UI, наши наработки могут пригодиться командам разработчиков и дизайнеров, которые хотят стилизовать свои продукты быстрее и удобнее.

Зачем перекрашивать готовые сервисы

Когда приложение или веб‑сервис находятся на начальной стадии (условный MVP), то команда в большей степени фокусируется на полезных функциях. Но с развитием продукта вокруг него выстраивается всё более сильный бренд, появляется сообщество лояльных пользователей. Стилизация нужна для уникальной идентификации такого бренда, с которым у комьюнити уже выстроены доверительные отношения.

Какие трудности могут возникнуть на этом пути:

  1. Однажды разработанный UI/UX может устареть. Мы все много раз наблюдали, как с развитием технологий пользовательские привычки менялись. Например, с появлением всё более удобных мобильных устройств у изначально ориентированных на десктоп сайтов появлялось всё больше мобильных пользователей. А когда‑то продуманные до мелочей веб‑интерфейсы — становились первыми кандидатами на ребрендинг.

  2. В уже готовую экосистему захочется добавить новую функциональность на базе сторонней библиотеки. Это как раз наш пример с DataLens — поскольку этот сервис позволяет быстро визуализировать данные из самых разных источников, то с его помощью можно легко добавить визуальные элементы на сайт. Но если у сайта своя узнаваемая дизайн‑система, то важно, чтобы виджет или дашборд из DataLens был как бы частью сайта.

  3. У продукта может появиться новая аудитория с новыми привычками. Сервис может выйти на новый рынок, где пользователи ведут себя совсем по‑другому. Например, предпочитают тёмную тему или пишут и читают не слева направо, а справа налево, и нуждаются в поддержке RTL в интерфейсе.

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

Что необходимо учесть при стилизации

При любой такой стилизации важно соблюдать несколько правил:

  1. Учитывать контрастность при замене цвета. Она не должна сильно отличаться от принятых стандартов WCAG.

  2. Оставлять прежними семантические цвета, например, сигнальные цвета состояния системы: красный — всё плохо, зелёный — хорошо.

  3. Не рекомендуется менять свойства существующих компонентов (например, размеры).

  4. Аккуратно менять цвет обводки, фона, и радиус скругления. Если ваша задача сделать сервис для повседневных задач, то не стоит сильно уходить от значений основных элементов. Так, в GravityUI все стили и цвета уже подобраны так, чтобы дизайн был «незаметным» для повседневного использования, чему могут мешать, например, явные тени или блюр.

  5. Логотип лучше менять в пропорции 1:1. Не рекомендуется менять иконки, которые уже сделаны по стандартам. Если заменить иконки всё‑таки нужно, то важно соблюдать их формат и размерную сетку.

Что такое Gravity UI, какие возможности стилизации тут есть

01.png

Gravity UI содержит набор библиотек и компонентов для создания функциональных интерфейсов. Внешний вид компонентов гибко настраивается, и в Figma есть открытая компонентная библиотека дизайн-системы со своими константами. Я расскажу об основных.

Цвета

Gravity UI поддерживает работу с несколькими темами — есть светлая, тёмная и их версии с повышенным контрастом. Они основаны на двухслойной цветовой модели. Механизм темизации спроектирован для гибкой настройки цвета и поддержки айдентики брендов с разным набором требований.

Типографика

03.png

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

Радиусы скругления контролов

04.png

Одна из частей визуального стиля — радиусы скругления углов. В Gravity UI есть сет переменных для радиусов. Чтобы поменять радиусы в контролах, нужно изменить значения переменных.

В Gravity UI все правила и компоненты унифицированы, чтобы везде всё выглядело хорошо. Соответственно, стилизация в Gravity UI строится на изменении параметров переменных у перечисленных констант или компонентов. Всё, что нужно для стилизации, уже заложено в переменных — они специально вынесены отдельно, чтобы с ними можно было экспериментировать.

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

Что дают возможности стилизации? При изменении параметра переменной цвет элемента с ней меняется во всём продукте. Например, вы сделали основной цвет красным. Теперь на всех страницах будут красные кнопки, красные обводки, а выделенный текст будет подсвечиваться светло‑красным цветом. При этом время разработчика или дизайнера сэкономлено, и не пришлось менять цвета вручную во всём сервисе.

Как стилизовали DataLens

Как мы уже рассказывали, DataLens развивался одновременно как cloud‑native‑решение для клиентов Yandex Cloud и как внутренний инструмент в Яндексе. В сентябре 2023-го этот сервис визуализации должен был выйти в опенсорс. DataLens как продукт для пользователей облака уже имел свою стилизацию, а перед нами стояла задача стилизовать два других: внутренний сервис DataLens YandexTeam и DataLens OpenSource, — чтобы эти продукты отличались от облачного сервиса. Расскажу по порядку, как мы это сделали.

Выбрали подход

05.png

В новых стилизациях нам всё равно было важно сохранить консистентность и узнаваемость облачного сервиса. Для этого мы взяли готовую группу так называемых бренд‑цветов. Что здесь имеется в виду? Всего у нас было около 100 CSS‑переменных цветов, и 15 из них относились к бренд‑группе: туда были включены те переменные, которые отвечают за кнопки, выделения, радиусы скругления — всё то, что в первую очередь влияет на восприятие бренда. Для облачных сервисов палитра этих элементов строилась вокруг синего. А с использованием дизайн‑системы нам нужно было поменять значения переменных в нескольких местах, чтобы получить нужный результат.

В коде Gravity UI не существует такой сущности как бренд‑группы, а цвета распределены по своим группам:

  1. Text — группа переменных для цвета текста и иконок (тексты и иконки часто отображаются вместе, и есть смысл синхронизировать их внешний вид).

  2. Base — группа цветов для всевозможных подложек, заливок и фонов.

  3. Base Semantic — цвета подложек с окрасом Info, Positive, Warning, Danger, Misc. Предусмотрены значения как для Normal, так и для Hover‑стейтов. Могут подойти для некоторых типов инфографики, но не для всех. Группа выделена только в Figma. В коде это часть группы Base.

  4. Base Float — цвета подложек элементов, находящихся над основным фоном страницы. Группа выделена только в Figma, в коде это часть группы Base.

  5. Line — цвета обводок, линий, разделителей, рамок и любых других тонких элементов.

  6. Effects — цвета для затемнения контента, теней и т. д.

  7. Misc — группа с разными техническими цветами: для скроллбаров, осей графиков, фона тултипа в чарте. Подробнее о назначении каждой переменной можно прочитать в описании колорстилей в Figma или в Storybook.

С помощью Figma мы могли подобрать новые цвета и шрифты, а с помощью расширения Stylus переопределить переменные в браузере — то есть поддержать две новые темы для DataLens YandexTeam и OpenSource.

Нашли акцентный цвет

06.png

Сначала мы были в поисках акцентных бренд‑цветов для новых тем — это отличительный признак любого сервиса. Акцентный бренд‑цвет используют на кнопках, чекбоксах, свитчах, радио и других ключевых контролах компонентной библиотеки.

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

Подобрали остальные цвета

07.png

Отталкиваясь от бренд‑цвета, изменяя тон, мы подобрали дополнительные цвета, которые используются в сервисе: цвета обводок, фонов и ссылок.

Как и в случае с основным синим цветом DataLens, мы искали тон по центру цветовой шкалы, чтобы для остальных цветов можно было подобрать разные по насыщенности оттенки.

Многие цвета мы оставили прежними. Например, не меняли цвета иконок, семантические цвета и тени. Обычно эти цвета выступают в роли нейтральных и сигнальных, поэтому их лучше сохранить в прежнем виде.

Проверили цвета на контрастность

08.png

Проверили на контрастность сочетания цвета текста на цвете фона — например, какое получается значение контрастности текста на фоне кнопок или цвет текста на фоне выбранных элементов в списке. Согласно стандарту WCAG, значение должно быть больше 4,5 contrast ratio. Это нужно для того, чтобы точно определить, будет ли на разных мониторах одинаково смотреться цвет текста или линии на другом цветном фоне.

Проверили цвета в двух темах

09.png

Выбирая цвета, мы проверяли их сразу в двух темах на ключевых экранах сервиса, где можно было проследить, как меняются цвета контролов, ссылок и логотипа.

Поработали с типографикой

10.png

Типографика в Gravity UI основана на использовании двух шрифтов и набора стилей, в которых указаны шрифт, вес, кегль и интерлиньяж.

Во внешнем и внутреннем DataLens используется собственный шрифт Yandex Cloud — YS text.

Для опенсорс‑версии мы по умолчанию использовали Inter для обычного набора и заголовков и Menlo в качестве моноширинного. Inter доступен в Google Fonts, а Menlo предустановлен по умолчанию в некоторых операционных системах. Эти шрифты всегда можно заменить теми, которые соответствуют брендбуку.

Правила для стилей типографики (заголовки, подзаголовки, наборный текст и подписи) оставили такими же, как в DataLens Yandex Cloud.

Покрасили логотип и заменили фавиконку

11.png

В основе логотипа сервиса лежит бренд‑цвет, который сочетается с остальными акцентными элементами сервиса.

Перекрасили иллюстрации

12.png

С помощью Figma перекрасили иллюстрации для статусов и отклика сервиса при взаимодействии с пользователями.

Главный цвет в иллюстрациях — акцентный бренд‑цвет, а все остальные цвета мы подбирали, как и с обводками и фонами выше — где‑то усиливается тон, где‑то уменьшается, где‑то используется чёрный или белый цвет.

В Yandex Cloud используются свои иллюстрации, не предназначенные для опенсорса. Для кастомизации опенсорса мы использовали готовую библиотеку с иллюстрациями.

Как для стилизации использовали расширение Stylus

13.png

С помощью 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);
      
    }
    
}

Теперь во вкладке сайта можно проверить изменения.

14.png

Переменные для быстрой кастомизации

Базовые переменные бренд-цветов

Название переменной

За что отвечает

‑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.

Выводы

Благодаря возможности кастомизации мы из одного продукта сделали три разных по стилю. При этом везде используется одна кодовая база, что облегчает поддержку сервисов. У нас на это ушло до двух недель. А если бы мы разрабатывали новую стилистику сервисов с нуля, то потратили бы во много раз больше времени и сил.

Вот основные выводы, к которым мы пришли, работая над продуктом. Если захотите повторить наш путь, они будут вам полезны:

  1. При стилизации с помощью Gravity UI лучше не отклоняться от подходов, которые описаны в этой дизайн‑системе. Они помогут сделать кастомизацию не только DataLens, но и любого другого сервиса, построенного на Gravity UI.

  2. Кастомизировать так, чтобы приблизить дизайн интерфейса сервиса к дизайну вашего бренда. Мы рекомендуем буквально взять свой брендбук и сайт, поставить их рядом со стилизуемым сервисом и убедиться, что они однородны и целостны.

Надеюсь, наш опыт был полезен, буду рад в комментариях обсудить примеры ваших задач. А если вам интересен наш подход к дизайн‑системе, и хотелось бы работать в такой же парадигме — будем рады видеть вас в нашей команде. Примеры задач, которые мы решаем, можно посмотреть по ссылке в Notion.

Комментарии (6)


  1. Budarin
    25.04.2024 18:22

    А если бы перед началом разработки изучили бы опыт Material Design - не пришлось бы сейчас мучаться подбирать и изобретать! :)

    MD3 - просто песня с его инструментом по генерации и подбору цветов для светлой и темной теме по картинке, по брендовым и кастомным цветам


    1. Alexeyafonin Автор
      25.04.2024 18:22

      Добрый день. В статье описан опыт решения наших задач и более общий подход по подбору цветов для переменных, зашитых в дизайн-систему. В DataLens совсем недавно вышел инструмент для стилизации UI в платном тарифе, можно им воспользоваться для примерки цветов с его помощью.


      1. Budarin
        25.04.2024 18:22

        Вопрос не в конкретном инструменте, а в основных принципах дизайна ну отсюда вытекает естественный процесс генерации цветов.

        Material Design - это не про конкретную библиотеку компонентов - это про дизайн и проектирование на его основе любых дизайн-систем и библиотек компонентов (там собраны лучшие идеи и практики дизайна интерфейсов)

        Благодаря системному подходу в дизайне можно генерировать тысячи цветовых схем , которые будут консистентны и будут содержать контрастные цвета

        Посмотрите на Хром - там есть галочка динамически менять цветовые темы - он по несколько раз за день меняет цветовые схемы - они генерируются динамически!

        А так можно героически напрягаться и в конце месяца сгенерировать таки одну тему для продукта, руками подбирая цвета и даже потом какой-то инструмент изобрести, но это процесс от обратного

        После такой работы если вы прочтете Material Desing вы будете удивлены : блин а почему мы раньше это не прочли? мы бы не мучались и сделали все гораздо проще!


        1. Alexeyafonin Автор
          25.04.2024 18:22

          В статье также учитываются практики, рассказывается с чем можно столкнуться, что есть от части внутри и как можно делать быстро и безопасно. Когда с этим работаешь, все происходит иначе – тут в этом речь. Вы говорите про волшебную кнопку, а мы про то, что под капотом.


          1. Budarin
            25.04.2024 18:22

            Вы говорите как вы героически сражались с тем что сотворили не используя знания и системный подход к проектированию UI - да вы молодцы поборолись со своими же проблемами и смогли таки создать тему

            А я , пройдя такие же этапы разработки и лишь затем обнаруживший Material Design, рекомендую вам после всего этого процесса который вы прошли и которым идет большинство (не изучая теорию и лучшие практики бросаются что-то строить) изучить его - я думаю вы на многое взглянете другими глазами и узнаете что любую новую тему при системном подходе к проектированию UI не нужно героически создавать - она автоматически получается за пару секунд :) Думаю что после изучения Material Design у вас возникнет сильное желание переписать все сделанное ранее )


            1. Alexeyafonin Автор
              25.04.2024 18:22

              Мы все очень хорошо знакомы с material design, давайте опустим какие-то теории и начнем углубляться в практику, буду благодарен, если у вас получится привести реальный путь, как поменять стилистику в подобных сервисах, имея собственную дизайн-систему. Наверное будет польза.