Хабрахабр

Как оседлать радугу: история создания тёмной темы

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

Расскажу, как небольшой командой адаптировали 300 экранов и систематизировали все существующие в мобильных приложениях цвета — для этого мы синхронизировали их между платформами и вынесли работу с ними в единую дизайн-систему с токенами. Меня зовут Михаил Лихачёв, я ведущий дизайнер VK. Поделюсь впечатлениями о том, как нам теперь с этим живётся и усложнился ли процесс дизайна.

Зачем нужна тёмная тема

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

А её появление на всех девайсах iOS и Android наверняка не заставит себя долго ждать. Сейчас тёмная тема реализована не только в популярных приложениях, но и в операционных системах macOS, tvOS, в лаунчерах на Android.

Она оказалась действительно востребованной — сейчас тёмной темой на iOS и Android регулярно пользуется больше 20% аудитории. Для нас это было также реализацией долгожданной функции — о тёмной теме пользователи просили чаще всего.

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

С момента релиза первой версии VK App на iOS прошло более 6 лет, приложение пережило несколько редизайнов. Когда мы проверили всё приложение и собрали все цвета, у нас оказалось более 200 уникальных HEX-значений. Например, один цвет в HSB мог иметь разные HEX-значения в Photoshop и Sketch. Где-то до сих пор сохранились необновлённые экраны, а где-то встречались ситуации, когда один и тот же цвет имел значение, отличающееся крайне несущественно.

Можно сказать, что это несколько приложений в одном: новости, музыка, видео, истории, трансляции, целый мессенджер и множество других не менее важных разделов и сервисов. Наше приложение очень большое. У одних только новостей несколько видов отображения записей и более 15 типов прикрепляемых материалов. Мы насчитали 300−400 уникальных экранов, у каждого из которых множество состояний. Для такого приложения необходима более сложная система, где цвета были бы разбиты по уровням контраста, чтобы их было проще подбирать не только для тёмной темы, но и для новых контролов.

Мы подготовили в похожей системе три расширенных палитры: серую, холодно-серую и синюю. В плане организации системы цветов нам больше всего понравился подход из Material Design. Эти числа и стали идентификаторами цветов вместе с названием палитры — Gray 100, Blue 300 и так далее. При этом мы разбили цвета по уровням контраста с условными значениями от 0 до 1000, где 0 — это самый светлый, а 1000 — самый тёмный.

В ней Hue — цветовой тон, Saturation — насыщенность, а Brightness — яркость. При подборе цветов помогает цветовая модель HSB. Saturation и Brightness задаётся от 0 до 100%. Hue варьируется в пределах 0−360°, и мы используем в интерфейсах фиксированное значение 212° как наш брендовый цветовой тон.

Затем подмешиваем синий цвет с помощью Saturation по небольшой кривой, вместе с этим корректируя значения Brightness, чтобы сохранить нужную нам градацию контраста. Так как мы делим серую палитру на 10 главных оттенков, в Brightness используем шаг в 10%.

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

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

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

И вынести все эти цвета в один файл в виде статичных переменных, где каждый цвет из палитры имеет уникальное название. Подготовив предзаданную палитру, её нужно было применить в приложении, заменив более 200 имеющихся HEX-значений на новый набор из более 50-ти.

Ребята подготовили алгоритм, заменяющий цвет на ближайший из новой палитры, что значительно ускорило процесс. Этим занялись наши разработчики из команды инфраструктуры на iOS и Android. Затем мы проверили все экраны с тестировщиками, чтобы нигде не применился неподходящий цвет, и наконец взялись за тёмную тему.

Подбор цветов в тёмной теме

Для фона используем Gray 900 — цвет на один тон светлее чёрного, чтобы понизить контраст между фоном и текстом. Мы начали примерять цвета тёмной темы на макетах главных экранов, чтобы определиться с основными используемыми оттенками. Текст по этой же причине выбрали не белый, а Gray 100.

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

Таблица основных используемых цветов

Акцентные элементы остались синими — для тёмной темы был подобран более светлый и менее насыщенный оттенок. В тёмной теме мы использовали меньшее количество цветов: синяя шапка и синие кнопки стали монохромными, спектр используемых серых оттенков сузился, а холодно-серая палитра перешла в обычный серый, сохранив контраст.

Затемнение под ними не хотелось инвертировать в белый, и без дополнительных мер в тёмной теме обычный фон контента сливался бы с окружением. Были и проблемные места, например модальные окна и карточки. Чтобы этого избежать, для модальных карточек мы подобрали фон на тон светлее обычного, а также добавили обводку (пока только на Android), чтобы лучше отделять их от нижнего слоя.

Такие примеры показали, что нам нужна более гибкая система при реализации тёмной темы.

Подобрав на макетах соответствующие цвета для тёмной темы, мы стали переносить это дело в код.

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

Мы сделали схему в JSON-формате, внутри которой прописаны все токены с их значениями в каждой теме. Мы определились со следующим подходом, где токен — это уникальное название элемента или группы элементов (например, background_content), а его значением может быть только цвет из фиксированной палитры (например, White).

Такая схема очень похожа на CSS-файл с идентификаторами элементов и их стилями, но в формате JSON.


Как выглядит схема с токенами background_content и text_primary

Всё, что у нас получилось, доступно на GitHub:

  • палитра со всеми цветами и их уникальными названиями;
  • схема со всеми токенами и их значениями в светлой и тёмной темах.

Об этом с примерами кода на iOS можно почитать на слайдах Антона Спивака с его выступления на CodeFest. Из JSON-схемы разработчики на всех платформах генерируют код в необходимом для себя формате. Доклад о реализации на Android с выступления Арсения Васильева на AppConf можно посмотреть здесь.

К значению токена можно добавлять параметр alpha для указания дополнительной прозрачности цвета. Напомним, что мы решили сделать строгую систему, где можно указывать цвет только из внутренней палитры, то есть в значении токена нельзя прописать произвольный HEX-код цвета. Этот параметр мы планируем использовать для добавления отключённого состояния и состояния при касании у контролов, чтобы не добавлять в палитру те же цвета с другой прозрачностью.

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


Примеры часто используемых токенов

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

Sketch и Zeplin

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

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


Так выглядит токен в виде символа

Если не понятно сразу по названию или нужно уточнить, к какому элементу относятся токены, добавляем описание и делим токены на секции, описывая конкретные элементы. Такие токены мы добавляем рядом с макетами и отправляем всё вместе в Zeplin. Используя плагин Sketch Runner для быстрого поиска по названиям символов, мы получили свой конструктор описания тёмной темы в виде аннотаций к макетам.


Добавление описания о используемых токенах

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

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

Тестировщики могут сами заметить явно неправильный цвет и попросить помощи дизайнера — для исправления недочёта понадобится только название правильного токена. Ошибки в реализации тёмной темы можно будет найти уже на стадии тестирования при проверке скриншотов.

Обновления схемы

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

После слияния изменений разработчикам нужно подтянуть обновление UI-библиотеки, и тогда новые цвета появятся в следующей dev-сборке уже через 15 минут. Подготовив обновлённую схему, мы отправляем пулл-реквест в GitHub (запрос на изменение файла), который проверяется и одобряется разработчиками.

Это означает, что такая версия автоматически примениться не сможет, и перед обновлением версии UI-библиотеки разработчикам необходимо поддержать все изменения: обновить названия токенов, а если удаляемый токен где-то использовался, то нужно следовать комментарию из списка изменений, указывающему, какой токен нужно использовать вместо него. Чтобы переименовать или удалить токены в схеме, мы создаём мажорное обновление, поднимая её версию в GitHub.

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

Кроссплатформенность и VKUI

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

Это набор React-компонентов, с помощью которых можно создавать интерфейсы, внешне неотличимые от наших приложений. Кроме нативных приложений у нас есть VKUI. Кроме того, эта библиотека используется для создания сервисов VK Apps сторонними разработчиками. Мы используем VKUI, чтобы создавать тестовые продукты внутри VK, а также для экранов, которыми хотелось бы управлять с сервера без обновления приложения.

Для нас это как ещё одна платформа, которую мы поддерживаем, только она содержит переключение между iOS и Android. VKUI собран по тому же дизайну и с тем же набором компонентов, что и нативные приложения, поэтому применение схемы и поддержка тёмной темы не потребовала новых макетов.

А самое интересное то, что на этой странице можно вживую увидеть используемые нами компоненты с возможностью переключать тему и платформу. Посмотреть реализацию дизайн-системы VK в виде React-компонентов можно на VKUI Styleguide.

В ближайшее время мы займёмся обновлением документации VKUI и соберём больше информации о работе нашей дизайн-команды — будет много интересного ️

Отдельная тема для мессенджера

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

Шапка в светлой теме стала белой, чтобы сфокусировать внимание на общении, а синий стал более ярким и насыщенным.

К примеру, чтобы перекрасить шапку и поиск, потребовалось заменить значения соответствующих токенов: header_background, header_tint, header_text, search_bar_background, search_bar_field_background search_bar_field_tint и других. Мессенджер сделан на базе модуля сообщений из основного приложения, а это значит, что он использует те же компоненты и ту же схему для описания всех цветов.

Довольно простым способом мы смогли за короткое время перекрасить всё приложение, создав новую тему оформления.

Работа с графикой

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

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

Тень в них чёрная, а заливка карточки белая. На Android также есть 9-patch графика, которая используется, например, чтобы отрисовывать карточки с тенями. Чтобы не разбивать и здесь графику на два слоя, разработчики воспользовались режимом наложения цвета Multiply — таким образом чёрная тень не перекрашивается, и цвет применяется только на белом участке картинок, что нам и было необходимо.

Итоги

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

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

Так же и с токенами — они запоминаются благодаря вложенному в них смыслу, а соблюдение логики в стилях, использующихся на нескольких платформах и приложениях, становится обязательной частью процесса. Когда появились понятные названия, отражающие контраст цветов, по ним стало гораздо проще ориентироваться, чем по HEX-значениям.

Но оно того стоило — тёмная тема собрала положительные отзывы пользователей, а комментарии «тёмная тема», распространившиеся на весь VK и даже вышедшие за его пределы, успели стать мемом. Процесс был трудоёмким не только для дизайнеров, но и для разработчиков и тестировщиков.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»