Ativando o Dark Mode em React.js com SCSS Modules 🌙
doug-source
Posted on July 18, 2024
Nota: apenas traduzi o texto abaixo e postei aqui. Atualizei um pouco apenas os códigos. As referências estão no fim deste artigo.
Em um de meus projetos recentes, precisei adicionar suporte para Dark Mode a uma Single Page Application (SPA) React.js. Como estávamos usando SCSS Modules para estilizar nossos elements, vamos explorar como implementar o Dark Mode em um projeto React.js com SCSS Modules.
Alternando entre Color Schemes
Com amplo suporte do navegador para variáveis ​​CSS, não vejo nenhuma alternativa ao uso da abordagem de body css class + variáveis ​​CSS. Isso significa que quando um usuário habilita o Dark Mode em sua application, uma css class .dark
é adicionada à tag body e as variáveis ​​são substituÃdas com base na presença ou ausência desta css class.
Variáveis ​​CSS
Se você ainda não conhece, variáveis ​​CSS (custom properties) são entities em CSS que permitem armazenar valores e usá-los em seus styles. Por exemplo:
body {
--text-color: #ccc; /** define uma variável CSS **/
}
h1 {
color: var(--text-color); /** obtêm o valor de uma variável **/
}
p {
color: var(--text-color); /** obtêm o valor de uma variável **/
}
Os nomes das variáveis ​​devem sempre começar com um dois hÃfen (--
), e você acessa uma variável usando a function var()
.
A function var()
tentará encontrar a variável --text-color
dentro de seu escopo ou do escopo de seus parents. No nosso caso, esse é o body. No entanto, você pode reset esta variável para que, por exemplo, os elements h1
e p
dentro das sections tenham uma color diferente:
section {
--text-color: #ddd
}
No nosso caso, esse truque ajudará a override as variáveis ​​do dark mode.
Caso real
Primeiro, declare todas as variáveis ​​que seus designers usam em layouts na pseudoclasse :root
e adicione-as a um arquivo global.scss
em seu projeto:
:root {
--black: #000;
--gray: #ccc;
--white: #fff;
--blue: #0085f2;
}
Nesse caso, sugiro não vincular nomes de variáveis ​​às entidades onde você planeja usá-las. Por exemplo, não nomeie elas como --text-primary-color: #ccc
, porque definiremos isso no nÃvel dos React component styles. Por exemplo, você tem um component:
import classNames from "classnames";
import { ComponentPropsWithoutRef } from "react";
import styles from "./Text.module.scss";
type TextProps = ComponentPropsWithoutRef<'p'> && {
type?: "primary" | "secondary";
}
export const Text = ({ type = "primary", children, ...remain }: TextProps) => (
<p
{...remain}
className={
classNames(styles.root, styles[`${type}Type`])
}
>{children}</p>
);
Como você pode ver, este é um React component simples que pode ter um de dois types, que pretendemos tratar no arquivo de style.
O arquivo de style (Text.module.scss
) para este component ficará assim:
.primaryType {
--text-color: var(--blue);
color: var(--text-color);
}
.secondaryType {
--text-color: var(--black);
color: var(--text-color);
}
Aqui, para cada text type, defini minha própria variável cujo valor é retirado da pseudoclasse :root.
Agora, para ativar o dark mode para text, precisamos usar a css class body.dark. Podemos fazer isso da seguinte maneira:
.primaryType {
--text-color: var(--blue);
color: var(--text-color);
}
.secondaryType {
--text-color: var(--black);
color: var(--text-color);
}
:global(.dark) {
.primaryType {
--text-color: var(--gray);
}
.secondaryType {
--text-color: var(--white);
}
}
:global(.dark) nos permite usar SCSS modules classes globais. Aqui, simplesmente substituÃmos os valores das variáveis, que, devido ao aninhamento dentro da css class .dark
, terão prioridade mais alta do que os declarados acima.
Como estamos usando SCSS, podemos criar um mixin baseado nesta abordagem. Vamos também adicionar uma media query para aplicar o dark mode com base nas configurações do sistema operacional do usuário.
Esta será a aparência do mixin:
SCSS Mixin
@mixin dark-mode {
@media (prefers-color-scheme: dark) {
@content;
}
:global(.dark) {
@content;
}
}
E aqui está como você pode usar este mixin:
@use "../styles/mixins";
.primaryType {
--text-color: var(--blue);
color: var(--text-color);
}
.secondaryType {
--text-color: var(--black);
color: var(--text-color);
}
@include dark-mode {
.primaryType {
--text-color: var(--gray);
}
.secondaryType {
--text-color: var(--white);
}
}
Dessa forma, os styles de dark mode dos seus components serão isolados e convenientemente localizados no final do arquivo, facilitando a navegação por eles. 🌙
Fonte
Artigo escrito por 0ro.
Posted on July 18, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.