DEV Community

Cover image for Utilizando pseudo-elementos do CSS e interfaces no TypeScript
Edeilton Oliveira
Edeilton Oliveira

Posted on

Utilizando pseudo-elementos do CSS e interfaces no TypeScript

Hoje vamos misturar CSS com TypeScript no mesmo post para entender como construir interfaces usando pseudo-elementos e interfaces! (what?)


Revisei pseudo-elementos no CSS durante o desenvolvimento do temporizador disponível aqui nesse link, mas não é de hoje que esses seletores me chamam a atenção. Acho interessantíssima a ideia de poder criar e estilizar um elemento que é renderizado em tela, sem a necessidade de adicionar elementos extras ao HTML ou ter que usar JavaScript.

Na especificação desse projeto, há uma tabela com uma coluna de status que tem uma bolinha (que pode assumir três cores diferentes) e o título do status, conforme mostrado abaixo, na coluna mais à direita:

Image description

Para criar essa bolinha, talvez o seu primeiro pensamento seja usar um componente estilizado dentro do td de status da tabela (mesmo que não seja um componente em outro arquivo, já que é algo simples). Daí teríamos dois elementos: a bolinha e o texto, com um gap entre eles.

Mas dá pra fazer melhor: pode ser só o texto com um ::before. E se você ainda não sabe o que é isso, vem comigo que eu te explico — e se já sabe, vem relembrar!

Utilizando pseudo-elementos

Resumidamente, ::before e ::after são pseudo-elementos do CSS criados, respectivamente, antes e depois da coisa que você tá estilizando. No exemplo abaixo (que utiliza Styled Components), estou criando a bolinha antes dessa div estilizada, já que ela fica à esquerda do texto:

export const Status = styled.div`
  display: flex;
  align-items: center;
  gap: 0.5rem;

  ::before {
    content: '';
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: ${(props) => props.theme['yellow-500']};
  }
`
Enter fullscreen mode Exit fullscreen mode

O background desse pseudo-elemento utiliza uma arrow function com props.theme somente por conta do Theme Provider da aplicação, mas você não precisa se preocupar com isso agora. Se preferir, por enquanto, imagine apenas uma cor fixa em hexadecimal e teremos o mesmo resultado.

Lembre-se que mesmo que você não queira exibir conteúdo algum dentro do pseudo-elemento, é sempre necessário usar o content: '';, caso contrário, ele não aparece na tela. Já na estrutura da página, cada linha da tabela será assim:

<tr>
  <td>Tarefa X</td>
  <td>30 minutos</td>
  <td>Há 3 meses</td>
  <td>
    <Status>Concluído</Status>
  </td>
</tr>
Enter fullscreen mode Exit fullscreen mode

Agora que o texto e a bolinha já aparecem na página, vamos pro próximo passo: mudar a cor de acordo com o status do componente.

Adicionando uma interface em TypeScript

Como alterar a cor no arquivo de estilos de acordo com o status da tarefa? Fácil: passando propriedades, mais ou menos como fazemos em componentes JSX.

Para isso, você pode criar uma interface no arquivo de estilos e passar pro componente usando os generics do TypeScript. Confira abaixo:

interface StatusProps {
  statusColor: 'green' | 'yellow' | 'red'
}

export const Status = styled.div<StatusProps>``
Enter fullscreen mode Exit fullscreen mode

E não podemos esquecer de passar a propriedade ao usar o componente lá na estrutura da página:

<Status statusColor="green">Concluído</Status>
Enter fullscreen mode Exit fullscreen mode

“E aí, tá pronto?”

Não.

Definindo a constante de cores

A cor ainda não muda pois tá fixa dentro do estilo do Status (no primeiro snippet de código desse post) e as cores que estamos utilizando ficam em um objeto que tá em outro arquivo, pois a aplicação utiliza o ThemeProvider do Styled Components. Você pode conferir conferir as constantes de cor no arquivo src/styles/themes/main.ts.

Para ter acesso a esses valores, uma solução é criar uma constante STATUS_COLORS, como é mostrado a seguir:

const STATUS_COLORS = {
  green: 'green-500',
  yellow: 'yellow-500',
  red: 'red-500',
} as const
Enter fullscreen mode Exit fullscreen mode

Por fim, lembra do background com o props.theme que poderia ser uma cor fixa? Agora precisamos tornar ela dinâmica, de acordo com o Theme Provider e a constante de cores que acabamos de definir. Veja no exemplo abaixo:

::before {
  background: ${(props) => props.theme[STATUS_COLORS[props.statusColor]]};
}
Enter fullscreen mode Exit fullscreen mode

Ou seja: pegue a propriedade statusColor (disponível nas props do componente), utilize como índice no objeto STATUS_COLORS e, com o valor retornado, acesse a cor desejada no theme do provider (também disponível via props, no arquivo App.tsx da aplicação).

Com isso — e contando que seu Theme Provider esteja configurado — o componente já deve alterar a cor da bolinha conforme o status passado por meios das propriedades. Lindo, né?

Vamos revisar o funcionamento:

  1. O componente Status recebe a cor pela propriedade statusColor lá no JSX;
  2. O estilo dele pega esse valor via generic do TypeScript — que está recebendo a interface StatusProps, definida nos estilos;
  3. Essa interface fixa que os valores aceitos são os mesmos da constante STATUS_COLORS;
  4. Os valores das chaves na constante STATUS_COLORS coincidem com os nomes das cores fornecidas pelo Theme Provider no arquivo App.tsx;
  5. O Theme Provider recebe o objeto mainTheme, contendo os hexadecimais das cores.

Facilitando a manutenção

Perceba que, na etapa 3 da revisão acima, os valores possíveis para a interface devem coincidir com a constante. Mas e se uma nova cor de status for adicionada ao componente? Precisamos editar a constante e a interface?

Até aí sim, mas podemos evitar isso adaptando a interface StatusProps para que statusColor sempre se ajuste aos valores das chaves da constante STATUS_COLORS. Confira:

interface StatusProps {
  statusColor: keyof typeof STATUS_COLORS
}
Enter fullscreen mode Exit fullscreen mode

Depois de dessa alteração, sabemos que sempre vamos ter uma equivalência entre as chaves de STATUS_COLORS e a lista de cores aceitas pela nossa interface. Agora não precisamos mexer em dois lugares ao modificar a lista de cores — basta alterar a constante.

Pronto! Agora, com tudo configurado, basta chamar o componente Status passando a propriedade que corresponda ao status da tarefa.

Concluímos que, além de uma solução bastante elegante, os pseudo-elementos no CSS são ferramentas excelentes para adicionar elementos em tela sem poluir o HTML ou recorrer ao JavaScript.

Em relação ao uso de interfaces em TypeScript e uma constantes de cores, percebemos que essas soluções tornam a implementação mais flexível e fácil de se adaptar a mudanças posteriores do projeto — o que torna a manutenção do código muito mais simples.

Curtiu aprender um pouco mais sobre o mundo do desenvolvimento front-end? Então me segue que em breve tem mais!

Top comments (0)