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.
Discover more from Coursity
Subscribe to get the latest posts sent to your email.