Как добавить в приложение переключатель тем, который наследует цветовую схему ОС в качестве состояния по умолчанию
Есть много хороших руководств по теме «темный режим», но редко те, которые охватывают две основные цели, на мой взгляд, такой реализации в реальном приложении. Это, соответственно, дает пользователям возможность переключаться между темами, наследуя по умолчанию цветовую схему ОС, заданную платформой, тем более, что и Google, и Apple начали развертывать такие режимы в своих продуктах.
Я пишу эту статью, чтобы поделиться решением, которое мы реализовали с помощью наших участников в нашем веб-редакторе с открытым исходным кодом для презентаций DeckDeckGo.
Начиная
Чтобы реализовать наше решение, мы используем два замечательных программного обеспечения:
- Idb-keyval: суперпростое, небольшое хранилище ключей на основе обещаний, реализованное с помощью IndexedDB, которое мы используем для сохранения выбора пользователя.
- RxJS: библиотека реактивных расширений для JavaScript, которую мы используем для хранения и распространения состояния, представляющего тему в памяти.
Мы собираемся использовать значение времени выполнения для переключения между темами. Следовательно, можно было бы реализовать такое решение, используя сохраненное состояние React Redux. Не сомневайтесь, пишите мне, если хотите получить такой пример; У меня также есть готовый вариант в другом новом приложении, которое я сейчас разрабатываю.
Синглтон-сервис
Чтобы управлять состоянием нашей темы, мы создаем одноэлементную службу Vanilla. Если вы используете фреймворк наподобие Angular, создайте службу с корневой областью, как обычно, или, если вы предпочитаете использовать функции и статические значения, сделайте это. Важно загрузить и сохранить в памяти только одно состояние, представляющее применяемую тему для всех ваших приложений.
В нашем сервисе мы объявляем логическое значение darkTheme
, которое со значением true
означает «активна темная тема», а false
- «активна светлая тема». Мы могли бы использовать enum
, если бы было доступно более двух тем. Возможность расширения - отличное преимущество этой реализации.
Обратите внимание, что мы используем ReplaySubject<1>
, так как хотим сохранить в памяти ровно одно состояние без значения, пока не выясним, какую тему применить.
Наблюдать и переключать состояние
Теперь, когда наша служба готова, мы должны раскрыть состояние приложения и предоставить пользователям метод переключения темы. Мы также должны сохранить выбор, чтобы он загрузился при следующем перезапуске приложения.
Начальное предпочтение
Во время загрузки мы должны загрузить тему в соответствии со следующими шагами:
- У пользователя уже есть предпочтительная тема?
- Не смогли ли мы прочитать эту информацию (возникает ли ошибка)?
- Следует ли использовать цветовую схему ОС по умолчанию, предоставляемую платформой?
Ответив на эти вопросы, мы создаем функцию, реализующую эту логику, и используем наш предыдущий метод switch
для распространения темы.
Примените тему к DOM
Мы специально не применяли тему «графически» в нашем сервисе. Следовательно, теперь мы должны решить, где мы хотим применить модификацию к DOM.
В наших проектах, поскольку мы разрабатывали наши приложения с веб-компонентами Stencil, мы начали инициализацию в корневом компоненте (app-root.tsx)
.
Более того, мы следим за изменениями в этом же компоненте, так как он не будет уничтожен, пока приложение не будет закрыто. Таким образом, при каждом новом генерируемом состоянии мы модифицируем нашу DOM, а точнее элемент body
, чтобы применить или удалить имя класса CSS (в нашем случае dark
).
Переключатель тем
До сих пор наше приложение могло обрабатывать только цветовую схему, предпочитаемую ОС, и не давало пользователям возможности переключать темы. Вот почему мы создадим новый компонент, который предоставляет, например, Ионный переключатель для переключения между светлым и темным режимами.
Укладка
Вы можете стилизовать темы с помощью переменных CSS или даже просто свойств. В обоих случаях важно применить тему в соответствии с именами классов, которые мы только что установили для элемента body
, соответственно dark
.
Если вы используете Ionic, вы сможете стилизовать определенный фон и цвет текста в вашем variables.scss
(:root
без селектора, являющегося светлой темой):
Или другой пример в простом HTML / CSS:
Все вместе
Наш проект DeckDeckGo имеет открытый исходный код. Поэтому позвольте мне поделиться с вами приведенной выше реализацией с некоторыми ссылками на GitHub нашего пульта дистанционного управления:
- Синглтон-сервис: Theme.service .ts
- Запускаем и смотрим: app-root.tsx
- Пример переключателя: app-general-settings.tsx
- Стиль: variables.scss
Вишня на торте
Возможно, вы на самом деле не заинтересованы в разделении кода на разные слои и просто хотите иметь один-единственный веб-компонент, который позаботится обо всем.
Угадай, что? У нас тоже есть такой компонент, который мы реализовали в нашей документации для разработчиков.
Кредиты
Как указано выше, мы разработали эту функцию с помощью наших участников, точнее с помощью Grant Herman. Он даже помог нам реализовать его в трех разных приложениях.
Определенно не все герои носят плащи; спасибо, Грант.