
Olá pessoal, meu nome é Vitalik, sou desenvolvedor sênior de front-end na Skyeng. Nossa equipe está criando uma plataforma Vimbox on-line para aprender inglês. Há cerca de um ano, o designer e eu concluímos um pequeno kit de interface do usuário que desenraizou o caos na interface e na base de código.
Aconteceu que não éramos os únicos na empresa que queriam o kit de interface do usuário, e outras equipes começaram a nos pedir conselhos sobre "como escrever o seu próprio". Conseguimos dissuadi-los desse empreendimento, prometendo moderar o nosso - isso salvou a empresa centenas de horas de desenvolvimento. Escolhendo uma solução, examinamos o Material Angular, montagens personalizadas e Variáveis CSS e, por fim, resolvemos o último, apesar de sua fraca compatibilidade com o SCSS, a base do kit de interface do usuário existente. Sob o corte - detalhes do que fizemos.

O problema
O primeiro kit de interface do usuário consistia em fontes, uma paleta, um conjunto de elementos para a criação de formulários (entrada, botão, etc.), um sistema para gerenciar ícones svg. Pop-up e dica de ferramenta baseada em materiais angulares também foram implementados. Ele foi preso por trabalhar apenas com o Vimbox "clássico": muitas coisas foram deliberadamente costuradas com firmeza e não permitiram mudanças externas. E a Skyeng começou a ter novos produtos na mesma plataforma, por exemplo, para crianças.
Os desenvolvedores de novas direções, sabendo que temos algo, vieram pedir conselhos. E, para nossa surpresa, eles já vinham com os layouts de seus kits de interface do usuário: eles iriam desenvolver suas soluções do zero, porque eles precisavam de uma aparência diferente para os componentes. Ficou claro que algo estava errado, e propusemos refinar nossa biblioteca, acrescentando a possibilidade de seu tema.
O argumento era simples: projetar nosso kit de interface do usuário levou 200 horas de design de UX e mais de 500 horas de desenvolvimento. Este é o tempo necessário para criar um sistema de fontes, cores e cerca de 10 componentes básicos. Assim, se você escrever uma biblioteca separada para cada produto, a empresa gastará N * 500 horas de tempo de desenvolvimento. Pensamos que melhorar o nosso kit de interface do usuário seria mais barato, além disso, essa etapa não precisaria ser repetida para cada produto.
Nossos argumentos foram aceitos, as áreas relacionadas concordaram em esperar e partimos para procurar uma solução técnica.
Dados de origem
Nossas ferramentas: Angular, SCSS.
Suportamos apenas navegadores modernos e, com algumas limitações, o IE11. O que facilita a vida.
Todos os nossos componentes do kit de interface do usuário foram imbuídos de estilos comuns que empilhamos no UI kit.var.scss
como constantes do SCSS:
@mixin fontSizeXl { @include fontSize(18px, 26px); } $colorSkillListening: #9679e0; $colorSkillListeningText: #7754d1; $colorSkillListeningBackground: mix($colorSkillListening, #ffffff, 16%); $colorSkillListeningBackgroundHover: mix($colorSkillListening, #ffffff, 8%);
Desafio
- Todos os novos produtos são montados a partir de elementos existentes no Vimbox "adulto" - salas de aula, contas pessoais etc.
- Os designers devem ter ampla liberdade para implementar idéias criativas, recursos distintos e requisitos específicos de novos produtos.
- Ao mesmo tempo, a continuidade permanece, ou seja, não importa quão cores ácidas e fontes loucas o designer invente, o pertencimento do resultado de seu trabalho ao ecossistema Skyeng permanece óbvio.
- Tudo isso é adicionado ao kit de interface do usuário existente, mantendo todas as suas vantagens.
Vamos lá!
Assim, o resultado é esperado de nós ontem, devemos realizar rapidamente análises técnicas e discutir opções. Nas primeiras reuniões, identificamos um círculo de possíveis soluções:
Material angular
Como não gostamos de escrever bicicletas, voltamos primeiro ao Material Angular. Nos componentes, os estilos dinâmicos são movidos para um arquivo {component}-theme.scss
. Esses estilos são vinculados ao seletor global do componente.
Variáveis CSS
Temos um ótimo motivo para experimentar as variáveis CSS da moda. O plano é transplantar as partes personalizadas do kit de interface do usuário para variáveis CSS. Os componentes usam as mesmas constantes SCSS, mas em vez de valores específicos, vars CSS são gravados nelas.
Construções personalizadas
Adoramos soluções simples, por que não tentar mudar a montagem? Cada equipe cria seu próprio arquivo com configurações de tema. Ao montar para todos os temas customizados, pacotes configuráveis separados com seu próprio tema são criados.
Solução
Durante uma semana, estudamos cada opção, discutimos, adiamos a decisão e estudamos novamente.
Adoramos novas tecnologias e as monitoramos, mas apenas as implementamos se elas nos derem bônus reais. Sabíamos das variáveis CSS, queríamos experimentá-las, mas a falta de funções do SCSS causou muita tristeza. No entanto, as vantagens dessa opção eram óbvias, decidimos descobrir como e quais funções SCSS usamos, se é possível fazer amizade com vars CSS.
Entendendo CSS vs SCSS
Depois de experimentar, percebemos que o principal problema é a falta de suporte para #hex no CSS: no SCSS, escrevemos rgba(#ffffff, 0.4)
, e no CSS a mesma coisa requer um conjunto diferente de parâmetros - rgba(255, 255, 255, 0.4)
. Tudo funciona para nós com #hex, e nós realmente, realmente não queremos mudar isso. Encontramos soluções, direi por ordem de admissão.
Clarear e escurecer
Nosso designer criou uma paleta composta por um pequeno número de cores básicas, expandindo-se devido às funções SCSS de lighten
e darken
:
Tentamos encontrar um análogo de lighten
e darken
no CSS, mas não encontramos nada. Pensamos por vários dias até percebermos que, para personalização, precisamos nos livrar dessas funções dentro da biblioteca, removendo-as. Afinal, cada equipe pode querer criar sua própria fórmula para mudar de cor ao mudar o foco - por exemplo, colegas da Kids precisam de mais contraste.
A solução simples foi transferir nossas transformações para o lado da plataforma que inicializará o tópico. E para a plataforma, estamos escrevendo uma função que cria automaticamente os valores necessários:
@function getMainColors($color, $colorText) { $colors: ( text: $colorText, base: $color, background: mix($color, #ffffff, 16%), backgroundHover: mix($color, #ffffff, 8%), lightenLess: lighten($color, 5), darkenLess: darken($color, 5), lightenMore: lighten($color, 20), ); @return $colors; }
A plataforma usa ao inicializar cores:
RGBA
Em nosso kit de interface do usuário, usamos a função rgba
. Com isso, ajustamos a transparência das cores de base. Mas se o rgba funcionar com #hex no SCSS, o CSS não poderá. Eu tive que escrever uma função que decompõe o valor #hex em r / g / b:
Bem, como não queremos gerar valores RGB com alças para toda a paleta, criamos uma função separada que faz isso recursivamente para cada cor da coleção:
Como resultado, a inicialização da paleta com os valores RGB gerados fica assim:
$colorValues: withRgbValues( ( text: ( base: #242d34, secondary: #50575c, label: #73797d, placeholder: #969b9e, inversed: #ffffff, inversedSecondary: #dadada, ), brand: getMainColors(#5d9cec, #4287df), positive: getMainColors(#8cc152, #55a900), accent: getMainColors(#ff3d6f, #ff255d), wrong: getMainColors(#ff6666, #fe4f44),
A saída é um mapa de cores SCSS, que pode ser transformado em um método que o transforma em variáveis CSS. Para obter o valor do tema RGB, escrevemos uma função:
@function getUiKitRgbVar($path...) { $path: set-nth($path, -1, #{nth($path, -1)}Rgb);
Transforme const SCSS em CSS vars
A primeira etapa é criar uma estrutura de espelho (semelhante ao SCSS) que armazene nomes de variáveis CSS:
$colorCssVars: withRgbCssVars( ( text: ( base: getColorCssVar(text, base), secondary: getColorCssVar(text, secondary), label: getColorCssVar(text, label), placeholder: getColorCssVar(text, placeholder), inversed: getColorCssVar(text, inversed),
getColorCssVar
- um método que adiciona prefixos aos nomes de variáveis. Adicione o prefixo --sky
para evitar colisões com bibliotecas externas. E também adicione o prefixo da biblioteca de - UI kit
a --sky
para evitar conflitos com bibliotecas internas. Descobriu --sky- UI kit
:
@function getColorCssVar($parts...) { @return getUiKitCssVar(color, $parts...); } @function getUiKitCssVar($parts...) { $uiKitCssVarPrefix: '--sky- UI kit'; $cssVar: $uiKitCssVarPrefix; @each $part in $parts { $cssVar: $cssVar + '-' + $part; } @return $cssVar; }
Por exemplo, para getColorCssVar(text, base)
obtemos --sky- UI kit-color-text-base
na saída.
O toque final é uma combinação recursiva que inicializa valores da estrutura SCSS para variáveis com nomes da estrutura Var CSS:
Um exemplo de uso de um tema na plataforma:
.popup { font-family: getUiKitVar(font, family); background-color: getUiKitVar(color, background, base); ... }
Qual é o resultado
Conseguimos usar variáveis CSS, mantendo a capacidade de usar funções SCSS. Criou a capacidade de personalizar a aparência dos componentes. Escrevemos alguns métodos recursivos para automatizar a extensão do tópico. Bem e mais importante - passou 30 horas de desenvolvimento em vez de N * 500.
Lucro!