Atualize temas e plugins para suportar modo escuro automático

Anteriormente, todas as cores no Discourse eram armazenadas como variáveis SCSS. Para suportar a troca automática de esquema de cores do modo escuro, convertemos essas cores no núcleo para propriedades CSS personalizadas. Você pode ver facilmente a lista completa no inspetor agora:

Temas e plugins precisam trocar todas as variáveis SCSS $color usadas em folhas de estilo pelas equivalentes propriedades CSS --color. Na maioria dos casos, esta é uma tarefa simples de localizar e substituir:

-   background-color: $primary-very-low;
+   background-color: var(--primary-very-low);

Mas há alguns casos em que um tema ou plugin está usando uma variação mais complexa de uma cor, por exemplo, ao escurecer ou clarear usando funções de cor SCSS. Esses casos exigem uma refatoração mais complexa, e para isso adicionamos a capacidade de estender as definições de cores em temas e plugins.

Em plugins

Este commit no plugin discourse-encrypt é um bom e simples exemplo de tal refatoração. Ele move uma declaração SCSS mix($color1, $color2) para um arquivo separado e a armazena como uma propriedade customizada CSS. Então, o novo arquivo é registrado como um asset :color_definitions, o que garante que a propriedade de cor recém-declarada seja incluída na folha de estilo de definições de cores.

Em temas

Em temas, você pode fazer a mesma coisa declarando propriedades customizadas CSS na folha de estilo common/color_definitions.scss. Você pode ver este commit no tema graceful como um exemplo.

Algumas notas adicionais

  • ao usar cores transparentes através da função rgba($color, 0.5), o SCSS aceita cores HEX e RGB no primeiro parâmetro, enquanto as propriedades customizadas CSS só aceitam uma cor RGB. É por isso que introduzimos o helper hexToRGB() e algumas propriedades com o sufixo --rgb nas definições de cores. Um exemplo:
// color_definitions.scss
:root {
  --primary: #{$primary};
  --primary-rgb: #{hexToRGB($primary)};
}

// outra folha de estilo
.element {
  background-color: rgba(var(--primary-rgb), 0.05);
}
  • note que no trecho acima, a variável SCSS é interpolada quando passada para uma propriedade customizada. Isso é um requisito no SCSS, veja Sass: Property Declarations para mais detalhes.
  • a declaração CSS var() pode ter um valor de fallback para um segundo valor se o primeiro não estiver disponível, como em, ao escrever var(--color1, red), o CSS fará fallback para a cor vermelha se a propriedade --color1 não for encontrada. Em plugins, usamos as variáveis de cor SCSS como fallbacks para garantir compatibilidade com versões anteriores do Discourse. Então, o exemplo anterior ficaria assim com um fallback:
-   background-color: $primary-very-low;
+   background-color: var(--primary-very-low, $primary-very-low);

Este documento é controlado por versão - sugira alterações no github.

24 curtidas

Não sou muito bom nisso e vai levar um tempo para eu entender sozinho… Isso significa que todos os temas que referenciavam cores anteriormente agora vão quebrar?

6 curtidas

Não, de forma alguma. Variáveis SCSS em temas continuarão funcionando por muito tempo.

No entanto, as cores geradas por meio de variáveis SCSS permanecerão estáticas, ou seja, não poderão ser alternadas dinamicamente para um novo esquema de cores quando o navegador mudar do modo normal para o modo escuro. Assim, esses temas e plugins continuarão funcionando, mas não serão compatíveis com a alternância automática para o modo escuro.

13 curtidas

Obrigado pelas instruções. Existe alguma maneira de também alterar uma imagem de fundo dependendo do modo escuro/claro? (Já usei o componente de alternador de tema para fazer isso.) Seria possível usar uma classe CSS indicando o modo?

2 curtidas

Ótima pergunta! Testei isso e notei que não havíamos implementado corretamente o suporte para uso de imagens de fundo ou variáveis de tema nas definições de cores especiais da folha de estilo. Por isso, fiz algumas correções no núcleo, e agora você deve conseguir fazer isso (certifique-se de atualizar para a versão mais recente do núcleo).

Assim, se você tiver duas imagens no seu tema ou componente de tema, com variáveis SCSS chamadas $bg-light e $bg-dark, respectivamente, pode adicionar o seguinte à sua folha de estilo color_definitions.scss:


$bg: url(dark-light-choose($bg-light, $bg-dark));

:root {
  --custom-bg: #{$bg};
}

E então você pode usar var(--custom-bg) na sua folha de estilo regular.

8 curtidas

Para uma imagem, tudo o que você precisa fazer é usar a media query CSS vanilla prefers-dark-theme.

Isso não funcionará bem em todos os casos, porque a consulta de mídia não tem conhecimento das preferências do usuário. Os usuários podem desativar a troca automática de modo escuro, mas a consulta de mídia não saberá disso, e isso resultará na renderização do plano de fundo destinado ao esquema de cores escuro.

4 curtidas

É possível o Discourse também adicionar uma classe CSS ao <body> para o esquema de cores ou ID do esquema de cores? Parece que seria muito mais fácil.

Estou tentando resolver um problema durante a conversão de um tema onde preciso de muitas regras CSS e variáveis diferentes, e isso está se tornando uma bagunça complexa no arquivo color_definitions.scss.

Se eu pudesse fazer algo como isto em um arquivo SCSS isolado no tema, levaria 5 minutos para fazer algo que está demorando muito para descobrir com color_definitions.scss:

body.dark-palette .some-thing {
  // alguns estilos
}

body.light-palette .some-thing {
  // alguns estilos
}

Sim, você pode acabar com muitas linhas de código nos arquivos de definição de cores, especialmente para gradientes.

Ainda é o “lugar” mais apropriado para isso na minha opinião. Está longe do elemento onde é usado, sim, mas é um local único e conveniente que lida com cores/gradientes que mudam com base no modo claro/escuro.

Uma alternativa é usar algo como isto:

@container style(--scheme-type: light){
  body{
    background: red;
  }
}

Nossos esquemas de cores vêm com uma propriedade --scheme-type que é light para esquemas claros e dark para esquemas escuros. Navegadores recentes suportam consultas de contêiner, então isso deve fazer o que você está tentando realizar aqui sem adicionar uma classe ao corpo da página.

Minhas habilidades em CSS/SCSS não são ótimas. Talvez isso seja mais fácil para pessoas que estão imersas nessas linguagens.

Estava bagunçando o arquivo color_definitions.scss, então o movi para outro arquivo em scss/ para poder importá-lo. Não tenho certeza de como nomear tudo, então está assim.

Acho que seria mais fácil fazer com uma classe body (ou talvez mais alguns exemplos), mas, de qualquer forma, está funcionando por enquanto. Não sei como as consultas de contêiner funcionam, mas pesquisarei mais tarde.

Note que consultas de estilo para propriedades personalizadas não funcionam no Firefox a partir de hoje (14/11/2025).