Já criou seus icones de forma dinamica?

Esse ano meu foco trabalhar mais com React, ainda quero postar alguns artigos que sobre NodeJS que estão no forno e com um pouco da experiencia que vi no ultimo ano. Mas o foco aqui é sobre algo que estou usando e achei bem impressionante.

Sabe aquele icone de font e você usa css para e a propriedade color para modificar ele? Então uma boa prática é usar um SVG no lugar dele, mas ainda melhor é quando você pode modificar ele contextualmente. Aí é que entra isso com React.

A forma de fazer isso isso é simples e se quiser dicas mais avançadas tem esse artigo muito bom em que me inspirei para criar um icon-system para um projeto que estou trabalhando.

Creating an SVG Icon System with React

Criando seu icone

O objetivo é mostrar o funcionamento do svg e do React, então para você já testar pode usar esse SVG aqui que exportei do AdobeXD.

<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
  <defs>
    <style>
      .a{opacity:0.5;}.b{fill:none;}
      .c{fill:#7614cc;fill-rule:evenodd;}
    </style>
  </defs>
  <g class="a">
    <rect class="b" width="16" height="16" transform="translate(0 0)"/>   
    <path
      class="c"
      d="M6.58,9.47A2.786,2.786,0,0,0,9.371,6.679,2.872,2.872,0,0,0,6.58,3.788,2.786,2.786,0,0,0,3.788,6.579,2.942,2.942,0,0,0,6.58,9.47ZM1.894,1.894a6.626,6.626,0,0,1,9.371,9.371L6.58,15.95,1.894,11.265A6.807,6.807,0,0,1,1.894,1.894Z"
      transform="translate(0.975 0.05)"/>
  </g>
</svg>

E no React vamos usar um componente de função, ele não precisa guardar estado e se tivesse algum poderia ser usado através de hooks ou classes como você achar melhor o segredo está no render.

import React from 'react';

export default (props) => (
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
  <defs>
    <style>.a{opacity:0.5;}.b{fill:none;}.c{fill:#7614cc;fill-rule:evenodd;}</style>
  </defs>
  <g class="a">
    <rect class="b" width="16" height="16" transform="translate(0 0)"/>
    <path class="c" d="M6.58,9.47A2.786,2.786,0,0,0,9.371,6.679,2.872,2.872,0,0,0,6.58,3.788,2.786,2.786,0,0,0,3.788,6.579,2.942,2.942,0,0,0,6.58,9.47ZM1.894,1.894a6.626,6.626,0,0,1,9.371,9.371L6.58,15.95,1.894,11.265A6.807,6.807,0,0,1,1.894,1.894Z" transform="translate(0.975 0.05)"/>
  </g>
</svg>)

Pronto assim você já tem seu component svg, mas ainda não está dinamico.

Deixando dinamico

Para isso é vamos usar prop, o que pode facilitar o uso do nosso icone, por exemplo se você tem icones quadrados, não precisa usar propriedades como height e width, mas pode criar uma abreviação como size.

O que queremos deixar dinamico são as cores, tamanho e opacidade do icone. Se você olhar o código temos uma parte de estilo que define um pouco disso para nós. Vamos começar criando uma propriedade style onde está as tags com essas classes, para facilitar, mas também poderia ser uma string concatenada.

import React from 'react';

export default (props) => (
<svg xmlns="http://www.w3.org/2000/svg" 
  width={props.size}
  height={props.size} viewBox="0 0 16 16">
  <g style={{opacity: props.opacity}}>
    <rect style={{fill:none}} width="16" height="16" transform="translate(0 0)"/>
    <path style={{fill:props.backgroundColor, fillRule: 'evenodd'}} d="M6.58,9.47A2.786,2.786,0,0,0,9.371,6.679,2.872,2.872,0,0,0,6.58,3.788,2.786,2.786,0,0,0,3.788,6.579,2.942,2.942,0,0,0,6.58,9.47ZM1.894,1.894a6.626,6.626,0,0,1,9.371,9.371L6.58,15.95,1.894,11.265A6.807,6.807,0,0,1,1.894,1.894Z" transform="translate(0.975 0.05)"/>
  </g>
</svg>)

Importante dar atenção que removi todo as classes css e criei inline-styles, isso facilitar para criar os dinamismo que queremos e também reduz o tamanho do nosso componente.

Uma outra coisa importante é que alguns nomes de propriedades css mudam, por exemplo o fill-rule vira fillRule isso por conta da forma que o react trabalha com esse tipo de estilo. E também a propriedade fillque é usada para preencher a cor dos paths do svg, criamos uma abastração como backgroundColor, mas pode ser qualquer outra que você achar melhor.  

Também foi removido o <defs><style>, isso quer dizer menos código e menos manutenção e trafego para o usuário, o código fica mais limpo. Paranoia minha e você pode fazer da forma que achar melhor.

Usando

Agora só dar o import como desejarmos:

import React, {Component} from 'react';
import pin from './pin'; // sim o icone é um pin

class UsingPin extends Component {

    render() {
        return (
            <Pin size="60" opacity="0.3" backgroundColor="#FF0000" />
        )
    }

}

Já deu para notar agora que é possivel fazer, por exemplo mudar de cor ao clicar ou até modificar o caminho do svg e assim vai. Espero que essa dica seja util.


Dúvidas, sugestões e correções você pode em encontrar procurando por flpmsno Google ou Twitter.

A foto é de minha autoria. :)