Привет, Хабр! Меня зовут Сергей, в ispmanager я отвечаю за дизайн продукта. Сегодня я хочу рассказать о том, как мы для ispmanager темную тему делали. Присаживайтесь поудобнее – несмотря на кажущуюся простоту, это была весьма объемная работа. А значит и история выйдет большая и занимательная. Поехали!

Почему мы вообще решили делать темную тему? Если кратко, это в этом мы видели возможность не только освежить UI продукта, но и позаботиться о пользователях ispmanager. Выбор темной темы далеко не всегда обусловлен эстетическими соображениями. Для людей, работающих за ПК ночью, dark mode — скорее необходимость, чем прихоть.

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

Ispmanager – продукт с солидной историей. Долгое время он обходился без четких правил применения цветов и унифицированных компонентов. Кроме того, логично, что за 18 лет развития проекта через него прошло немало людей и каждый из них мог оставить свой скромный отпечаток.

Сбор данных

Театр, как известно, начинается с вешалки. А тема приложения — с палитры. Первым делом мы решили сверить фактическую палитру с той, что прописана в нашей дизайн-системе, а заодно подсчитать реальное количество используемых цветов.

Я предполагал, что в самом запущенном случае мы используем порядка 30-40 оттенков: несколько синих, несколько серых. Красный, желтый, зеленый… Забегая вперед, скажу: даже в самых смелых прогнозах я был чертовски далек от истины.

Палитра ispmanager до структуризации
Палитра ispmanager до структуризации

Мы с фронтенд-разработчиком Бориславом провели дотошный анализ того, как и где используется тот или иной цвет. Нам пришлось проверить буквально каждый уголок продукта, чтобы убедиться, что мы ничего не забыли. По итогу выяснилось следующее:

  1. Палитра в дизайн-системе существенно отличается от фактической.

  2. Некоторые цвета имеют «дубли», без которых можно (и нужно!) обойтись.

  3. Нейминг цветов малоинформативен и требует доработки.

  4. Компоненты остро нуждаются в унификации.

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

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

Для удобства я разложил получившуюся палитру в Figma и расписал для каждого цвета зону его применения. Чтобы начать оптимизацию, мне необходимо было по каждой группе «дублей» ответить на следующие вопросы:

  • Можно ли в конкретном случае «слить» два похожих цвета в один?

  • Как именно лучше объединять цвета, какой именно оттенок лучше подходит?

  • Как именовать получившиеся цвета, чтобы получилось удобно и универсально?

Задача со звездочкой — цвета, имеющие атрибут прозрачности.

Подбор и нейминг новых цветов

Итак, после подбивки текущей палитры я собрал еще один стенд и разложил на нём используемые цвета по принципу «можно слить» и «нельзя слить». А еще ставил «горчичники» (пометки), чтобы ничего не забыть и фронту было понятно, что, как и куда перемещается. Вот так выглядел этот стенд:

По вертикали — объединяемые цвета. По горизонтали – разные оттенки, которые нужно сохранить.
По вертикали — объединяемые цвета. По горизонтали – разные оттенки, которые нужно сохранить.

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

Спустя какое-то время палитра приобрела следующий вид:

Согласитесь, прогресс налицо. Из ~100 цветов и оттенков я выделил всего 15-20 минимально необходимых. Единственное, что бросается в глаза – оставшийся от легаси неоптимальный нейминг. Требовалось его как следует переработать и привести названия цветов к общему знаменателю. Но как лучше это сделать?

Изначально цвета в продукте имели странную систему идентификации. Вот, например, список желтых: isp-yellow-3, isp-yellow-7, isp-yellow-8, isp-yellow-9, isp-yellow-6, isp-yellow-11. Куда делись все пропущенные порядковые номера? Загадка!

Если взять Google Material, там всё четко. Цвета разбиты по оттенкам, у каждого есть градация от светлого к темному. Аккуратная нумерация – всё по полочкам и ничего не выпадает. Соответственно, нам требовалось выработать новый подход к именованию цветов – а заодно принципы создания новых оттенков.

  • Нумерация? Она не даст нам достаточной гибкости. Что если нам понадобится ввести цвет, находящийся между синим №5 и синим №6?

  • Стандарт sRGB или X11? Недостаточно универсально и не очень удобно. Пришлось бы вводить массу лишних цветов. К тому же нам хотелось чего-то «своего».

А что, если мы для каждого получившегося цвета придумаем уникальное «фирменное» название? Причем такое, чтобы легко запоминалось и нравилось фронтенд-разработчикам. Идеально!

Пожалуй, это был самый веселый и приятный этап работы. Так в нашей дизайн-системе поселились Jon Snow, Fantomas, Nosferatu, Malewicz и прочие цветные знаменитости. Такая палитра позволяет проще разрабатывать стили, поскольку у разработчиков постепенно возникают ассоциации с названиями цветов. 

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

Важный момент! Все цвета в интерфейсе нужно тестировать на контрастность по WCAG. В этом могут помочь плагины для Figma «Contrast» и «Color blind».

Что касается оттенков серого — раньше они были совершенно разнокалиберными. Одни уводило в зеленый, другие – в синий… Я полностью убрал оттенок и сделал их ахроматическими. Теперь у серых цветов остался только один параметр – светлота.

Отдельного внимания заслуживает принцип введения каждого нового цвета. Его следует строить от основного цвета путем изменения значений насыщенности и светлоты на число, кратное 5. Так мы можем гарантировать, что палитра получится однородной, а разработчики не будут «дергать» цвета из головы и при необходимости смогут просто высчитать нужный цвет из базового. Фронтенд-команда приняла решение больше не использовать «сырые» значения при разработке компонентов — только переменные с цветом (значения разрешено использовать только для определения переменной цвета).

Чтобы с палитрой было не только удобно, но еще и приятно работать, она нашпигована отсылками к кинематографу, видеоиграм, известным личностями, да и просто веселыми названиями типа «похмелье».

Все отсылки угадали? 
Все отсылки угадали? 

Работа с интерфейсом

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

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

Ispmanager в светлой теме
Ispmanager в светлой теме

У объектов на переднем плане есть тень. Она появилась там не случайно. Тень позволяет визуально «приподнять» элемент и мягко выделить его на фоне окружения. Это не просто красивость, она на самом деле помогает пользователю лучше ориентироваться в продукте.

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

Ispmanager в темной теме
Ispmanager в темной теме

Благодаря обводке мы можем увидеть контур объекта. В светлой теме обводка тоже присутствует – она светлого-серого цвета и практически незаметна, но на дисплеях с плохой передачей контрастности играет важную роль. При этом от теней мы решили не отказываться. На темном фоне они, конечно, растворяются, но не на 100% благодаря тому, что мы не используем в качестве фона абсолютно черный цвет.

Добавив обводку, мы столкнулись с еще одним нюансом: интерфейсу не хватало «глубины», а в формах при открытом select’е вообще началась путаница. Поэтому все модальные окна, списки и уведомления мы покрасили в более светлый тон по принципу «то, что дальше – темнее, то, что ближе – светлее».

Благодаря более светлому оттенку выпадающий список не теряется на фоне основного интерфейса
Благодаря более светлому оттенку выпадающий список не теряется на фоне основного интерфейса

Динамические цвета

Первой идеей при разработке темной темы была замена всей палитры на «темную». Однако сразу возникли некоторые проблемы. И главная — это «древовидная зависимость» цветов. Давайте поясню, что это такое.

Представим, что всё приложение состоит из четырех переменных для цвета.

:root {

--isp-c-grass: #00C9A7;

--isp-c-sun: #FEFEDF;--isp-c-flower: #F3C5FF;

--isp-c-obsidian: #845EC2;

}

Дизайнер решил, что в темной теме obsidian нужно заменять на flower, а flower — на sun. Остальные цвета остаются неизменными. Таким образом цвета для темной темы будут выглядеть так: 

.dark-scheme {

--isp-c-flower: var(--isp-c-sun);

--isp-c-obsidian: var(--isp-c-flower);

}

Однако теперь obsidian тоже будет иметь значение sun, так как он стал «зависимым» от цвета flower.

Следующая идея была такая: определить по компонентам переменные и присвоить им цвета. Однако ее мы тоже быстро отмели из-за большого количества компонентов.

Изучив опыт других компаний и их дизайн-системы, команда сошлась на варианте с использованием цветовых токенов (color tokens). Основная проблема в данном решении — время. Нужно изучить 600+ мест с цветами и объединить некоторые из них по общим областям применения.

Иными словами, нужно было придумать что-то такое, чтобы не пришлось анализировать все цвета в проекте, но можно было поменять некоторые из них. Так мы и пришли к идее динамических цветов.

У каждого цвета темной темы есть свой негативный «близнец», доступный в палитре статических цветов. Так, Малевич перекрашивается в Гэндальфа Серого. Каждому компоненту при его создании одним атрибутом прописывается цветовая пара «светлый/темный».

Наступает ночь, и Гэндальф превращается в Малевича
Наступает ночь, и Гэндальф превращается в Малевича

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

В динамической палитре каждый цвет изменяется в зависимости от текущей темы. Например, --isp-dc-cheese (префикс dc означает dynamic color) будет светло-желтым в светлой теме и темно-коричневым в темной теме. Данное решение позволяет никак не трогать текущую цветовую палитру. Достаточно в компоненте заменить статический цвет на динамический. Если же цвет вообще не изменяется от темы, можно просто использовать статический цвет.

Ispmanager в темной теме
Ispmanager в темной теме

Итоги и планы на будущее

На сегодняшний день я могу сказать, что на 90% темная тема выглядит так, как мы задумывали. Палитра и перекраска компонентов корректировалась на протяжении всего процесса разработки и тестирования, но нюансы все равно остались. Например, где-то недостает контрастности, которая хромает и в светлой теме. Иконки – это отдельная тема, достойная еще одной небольшой статьи. Поскольку передо мной стоит чуть более глобальная задача, нежели внедрение темной темы (я говорю сейчас о поднятии уровня дизайна приложения в целом), всё это со временем будет решено и выкачено на прод.

Один курьезный момент. Помните! Все макеты темных тем должны тестироваться в темном помещении. Я сам с этим столкнулся: днем макетировал в Figma, днем же проверял. А когда открыл макет ночью, оказалось, что с серыми цветами я прогадал: нужно делать их темнее. Кстати, об этом уже рассказывала моя коллега, советую ее статью к прочтению.

Разработка темной темы оказалась более комплексной и сложной задачей, нежели могло показаться на первый взгляд. Тем не менее, ее реализация позволила не только непосредственно внедрить dark mode, но и добиться других улучшений в ключе дизайна продукта:

  • В процессе разработки темной темы мы улучшили светлую.

  • Повысили доступность интерфейса за счет контрастности.

  • Унифицировали компоненты и выработали систему.

  • Снизили стоимость обновления UI в будущем.

Текущая реализация темной темы еще будет полироваться. Прямо сейчас мы работаем над еще одним компонентом UI – карточки. Они призваны решить сразу две задачи:

  • Альтернативное отображение списков, более понятное и дружелюбное к новичкам.

  • Заполнение «пустого» пространства – если у пользователя добавлен всего один сайт.

Возможно, кто-то захочет нам возразить и скажет: 

«Вы не делаете новые фичи, только самое простое реализуете!»

На самом деле, новые фичи постоянно релизятся, над ними ведется активная работа. Подтверждение тому – дорожная карта проекта. Темная тема – точно такая же «фича», как и все остальное. Более того, пользователи сами проголосовали за ее скорейшее внедрение.

У запланирован выход многих вещей: поддержка Docker, Drag’n’Drop, новый центр загрузок, центр уведомлений, виджеты для главной страницы. По ним оставляли пожелания наши пользователи, и скоро всем это можно будет увидеть в ispmanager.

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