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.
Top comments (0)