Aguarde...

2 de abril de 2021

Modo escuro de construção

Modo escuro de construção

Como muitas empresas, temos uma Hack Week no Sentry. Em 2017, codificamos um aplicativo que tocava música de entrada para qualquer pessoa que entrasse em nosso escritório. Em 2019, incentivamos as pessoas a serem legais na Internet . Causas nobres, claro, mas para a Hack Week deste ano, eu estava determinado a promover uma causa próxima e querida ao meu frio coração britânico: o modo sombrio.

Mal sabia eu que o que começou como um pequeno projeto de semana de hack se tornaria um grande elevador que incluía cores pantone, códigos hexadecimais e todos os tipos de variáveis.

Mas primeiro as coisas mais importantes. Se você for para Configurações do usuário> Tema, poderá ativar o Modo escuro. Também adicionamos uma opção em que você pode alternar com base no tema do sistema padrão:

Dada sua recente popularidade, você pode acreditar que o modo escuro é uma moda passageira. Mas do ponto de vista do design, o modo escuro é excepcionalmente útil. Isso porque uma grande parte do design é sobre a construção de relações entre as cores. E, portanto, a implementação do modo escuro essencialmente forçou todos na equipe a pensar muito, muito e de forma consistente sobre nossos componentes de design de front-end. Resumindo, o modo escuro ajudou nosso sistema de design não apenas a ter uma boa aparência, mas também a fazer sentido.

Organizamos o trabalho em três grupos:

  1. Limpando variáveis
  2. Projetando o sistema
  3. Criação de aliases e componentes de refatoração

Limpando Variáveis

Quando comecei a explorar nossa base de código, encontrei todos os tipos de inconsistências de cores. Coisas como códigos hexadecimais dispersos e variáveis ​​únicas, como blueLightestou offWhitesendo usadas de todos os tipos de maneiras curiosas. Isso significava que sempre que um engenheiro queria realmente construir algo, ele era forçado a pensar por muito tempo e muito a sério sobre a cor que deveria usar.

Aqui está um exemplo: Eu quero adicionar uma borda a um componente. OK fixe. Quais variáveis ​​posso usar? Deixa eu ver. Eu gosto de cinza, então vamos usar cinza. Bastante simples, certo? Bem, existem dezoito cinzas – sem mencionar suas variáveis ​​de borda e códigos hexadecimais. Qual devo usar? Por que o design que estou procurando está usando uma nova cor de borda? Onde na minha vida tudo deu errado?

Nenhum engenheiro deve ser forçado a responder a essas perguntas, então começamos a limpar todo esse lixo. Para começar, fiz um mapa de cada variável que usa componentes React. Este mapa nada mais era do que uma planilha (bruto), mas serviu a um propósito importante: agora eu sabia quais variáveis ​​de cores obsoletas deveriam ser substituídas. Essa planilha nos ajudaria a fazer várias pequenas solicitações pull, nas quais poderíamos mudar yellowLightestpara uma nova variável chamada yellow400. Além disso, ao fazer muitas pequenas solicitações de pull para cada variável, também podemos limitar as regressões.

Felizmente, a maioria dessas variáveis ​​era armazenada em um único lugar, já que tínhamos sido bastante rígidos quanto a armazená-las no theme.tsxarquivo que importamos para nossos componentes React. Dentro desses componentes, aplicamos esses estilos ao emotion , nosso plugin css. Isso parece muito – e é – mas a emoção vale bem a pena a sobrecarga ao construir aplicativos complexos, pois nos permite isolar nosso CSS em um único componente, Dropdownpara que não tenhamos que nos preocupar com esses estilos sangrando em outros arquivos ou páginas.

Aqui está um exemplo de um componente que usa emoção:

import React from 'react';
import styled from '@emotion/styled';

const ComponentName = styled('div')`
  color: ${p => p.theme.offWhite2};
`;

export default ComponentName;

Para remover uma cor como offwhite2, eu precisei pesquisar em nossas bases de código e encontrar todos os componentes React que usavam aquela variável específica. Só então poderia substituí-lo por algo mais sensato. Em nosso theme.tsxarquivo, nós os organizamos em algo assim:

const colors = {
  white: '#FFFFFF',
  black: '#1D1127',

  gray100: '#E7E1EC',
  gray200: '#C6BECF',
  gray300: '#9386A0',
  gray400: '#776589',
  gray500: '#2B1D38',

  yellow100: '#FDE8b4',
  yellow200: '#FFD577',
  yellow300: '#FFC227',

  purple100: '#D4D1EC',
  purple200: '#A396DA',
  purple300: '#6C5FC7',

  blue100: '#D2DFF7',
  blue200: '#92A8EA',
  blue300: '#3D74DB',

  orange100: '#FFF1ED',
  orange200: '#F9C7B9',
  orange300: '#F69C7D',
  orange400: '#FF7738',
  orange500: '#BA4A23',

  red100: '#FCC6C8',
  red200: '#FD918F',
  red300: '#F55459',

  green100: '#B6ECDF',
  green200: '#7DD6BE',
  green300: '#33BF9E',

  pink100: '#FDC9D7',
  pink200: '#FA93AB',
  pink300: '#F05781',
} as const;

No total, esse processo levou semanas de trabalho de refatoração em tempo parcial, mas uma vez feito foi bastante satisfatório. Finalmente tínhamos uma lista de cores que eram em sua maioria consistentes, a tal ponto que sempre que um engenheiro viesse para construir algo, eles sabiam usar essas variáveis. E agora que havia menos opções em nosso sistema, poderíamos começar a pensar sobre as relações entre todas essas cores.

Projetando o Sistema de Cores

Ainda tínhamos algumas perguntas assustadoras para responder. Como estamos usando cores em nosso aplicativo hoje? Quais são os estados padrão ativo, flutuante e de foco? Quais são as cores comuns das bordas? Quais devem ser as cores do nosso texto? E, finalmente, como esses estados são representados em menus suspensos, campos de formulário, botões, alternadores, links e tags?

Para resolver essas questões, precisávamos de maquetes. Depois de reunir nossos componentes mais comuns no Figma, encontramos um monte de inconsistências em nossos estilos de texto e formulário, bem como em como aplicamos cores de borda a todos os nossos componentes. E assim, ao unificar todas essas inconsistências visuais (criando uma lista menor de variáveis), poderíamos fazer nossa IU funcionar para o modo claro e escuro ao mesmo tempo.

Aqui está um primeiro modelo desses componentes atualizados:

Este trabalho envolveu examinar vários recursos do Sentry – problemas, descobertas, versões, desempenho, alertas – para ter certeza de que o sistema de cores que funcionou para nossos gráficos também funcionou no modo escuro.

Em seguida, criamos uma paleta de cores de modo escuro separada para nossos gráficos:

Uma vez que sentimos que os estilos básicos tinham uma boa cobertura, começamos a estruturar a IU juntos no Figma. Isso não apenas nos permite pensar sobre como algumas dessas mudanças podem afetar os clientes, mas como podemos melhorar a acessibilidade em todos os nossos componentes:

Depois de nos movermos para frente e para trás entre nossos componentes menores e nossos layouts, finalmente estabelecemos nossa nova paleta de cores. Mais uma vez, lembre-se de que a ideia aqui não é apenas oferecer suporte ao modo escuro, mas resolver todas as questões pendentes em torno de como construir novos componentes. As pessoas não deveriam ter que dar folga à equipe de design para descobrir qual cinza usar para o texto cinza.

Um fato da vida para designers é ficar incomodado com suas próprias soluções. Por exemplo, fiquei um pouco irritado por termos uma backgroundvariável separada aqui, em vez de apenas adicionar um novo cinza. Mas faz sentido para nosso produto – e como queremos usar nosso sistema de cores. Quando meu sistema entra em conflito com um problema do mundo real, meu sistema precisa se curvar para o problema – não o contrário. A consistência é mais importante do que a pureza ideológica.

Foi nesse ponto que adicionamos as variáveis ​​do nosso sistema de design ao Figma, para que quaisquer novas cores que usarmos no futuro também usem essas versões atualizadas:

Agora tudo o que tínhamos que fazer era construir a maldita coisa.

Criação de aliases e componentes de refatoração

Sabíamos que queríamos que nosso texto de parágrafo ficasse gray500no modo claro, mas depois mudasse para whiteo modo escuro. Essa alternância entre os modos claro e escuro exigiria um apelido, como textColorpara alternar entre essas duas opções. Para fazer isso, precisamos criar vários apelidos em nosso theme.tsxarquivo.

Neste arquivo, primeiro definir a nossa gama de cores e, em seguida, criamos esses aliases como textColorsubText, e borderColor. Mas este não foi um processo fácil: discutimos muito sobre as convenções de nomenclatura e seu uso em nossos componentes. Só quando começamos a refatorar nossos componentes é que esses nomes começaram a fazer mais sentido.

const colors = {
  white: '#FFFFFF',
  black: '#1D1127',
  gray100: '#E7E1EC',
  gray200: '#C6BECF',
  gray300: '#9386A0',
  gray400: '#776589',
  gray500: '#2B1D38',
  // other vars go here
} as const;

const aliases = {
  /**
   * Primary text color
   */
  textColor: colors.gray500,

  /**
   * Text that should not have as much emphasis
   */
  subText: colors.gray400,

  /**
   * More...
   */
}

Os acrônimos acima são as cores do nosso modo de luz. Em seguida, começamos a criar os aliases de modo escuro neste arquivo enquanto refatoramos nossos componentes e adicionamos novos aliases conforme os encontramos. Neste mesmo arquivo, temos um novo objeto que contém todas as nossas cores para o modo escuro:

const darkAliases = {
  ...aliases,
  bodyBackground: colors.black,
  headerBackground: colors.gray500,
  background: colors.black,
  backgroundSecondary: colors.gray500,
  border: colors.gray400,
  innerBorder: colors.gray500,
  textColor: colors.white,
  // more aliases go here 
} as const;

Isso envolveu várias conversas sobre como nossos componentes se parecem em diferentes recursos – o que pode funcionar para um componente em um lugar, pode não funcionar para outro componente em outro lugar.

Começamos refatorando cada um de nossos componentes para trabalhar com esses novos aliases. Aqui, identificamos padrões comuns em que teríamos que substituir cada instância de uma variável por esses novos aliases. Um exemplo é a cor do texto: às vezes, isso era tão fácil quanto trocar todos os gray400s em nossos componentes e, às vezes, envolveria a verificação de cada componente para descobrir onde estávamos definindo gray500na colorpropriedade CSS. Isso significou muitas tentativas – e erros.

No entanto, uma das partes mais difíceis sobre esse projeto de refatoração é que todos os nossos estilos não estavam localizados em um só lugar. Embora nossas variáveis ​​e aliases tenham sido (de certa forma) armazenados ordenadamente em nosso theme.tsxarquivo, nossos estilos ainda estavam espalhados pelos seguintes minissistemas de CSS:

  • Estilos de bootstrap : ainda estamos dividindo esses estilos em .lessarquivos individuais e, em seguida, refatorando-os em nossos componentes React. Há uma tonelada de estilos não utilizados aqui que precisam ser eliminados e não estilizamos nada com nossas theme.tsxvariáveis ​​aqui.
  • Estilos de base : este é um base.lessarquivo que é redefinido e um .lessarquivo de normalização que fizemos após refatorar uma tonelada de coisas do Bootstrap. Esses são os estilos básicos para os elementos HTML padrão, portanto, também não podemos usar nossas variáveis ​​extravagantes a partir theme.tsxdaqui.
  • Estilos globais : Este é um .tsxarquivo que está substituindo um monte de coisas a partir de estilos Bootstrap e Base e faz uso de estilos de nosso tema. Idealmente, tudo do Base deve ser refatorado em nossos estilos globais, mas isso não é possível, pois algumas de nossas páginas ainda não estão no React.
  • Componentes : Como mencionei, cada um de nossos componentes usa emoção (que eu amo e estou um pouco incomodado) que substitui nossos estilos globais, que substituem nossos estilos básicos. Ufa .
  • Componentes estilizados: são variantes ou modificações únicas em nossos componentes usados ​​em um recurso como problemas ou alertas. É aqui que a emoção fica um pouco aquém para mim (e gostaríamos de estendê-la talvez com algo como Tachyons). Enquanto algumas dessas modificações são devidas ao fato de que nossos componentes precisam ser arrumados, outras são necessárias porque nossos padrões no Base e Bootstrap precisam ser totalmente excluídos. Ufa duplo .

Se você acha que tudo isso soa e parece um pesadelo absoluto, bem, não vou discutir com você. E, no entanto, acho que esse é o valor inerente ao modo escuro de construção: agora você pode ver todas as relações entre seus componentes e seus estilos e seu sistema de design.

Postado em Blog
Escreva um comentário