Skip to content

Latest commit

 

History

History
254 lines (194 loc) · 7.8 KB

File metadata and controls

254 lines (194 loc) · 7.8 KB

Na prática com Styled Components

Esse exemplo está na documentação 😄

Instalação

npm install styled-components

-- ou --

yarn add styled-components

⚠️ Observação: é altamente recomendado, mas não obrigatório, utilizar o plugin do Babel. Algumas vantagens são nomes de classes mais legíveis, SSR, bundle menor, e outros.

Iniciando

styled-components usa tagged template literals para estilizar os componentes. Essa abordagem elimina completamente o mapeamento entre estilo e componente. Ou seja, quando você define um estilo, você está criando um componente normal do React.

O exemplo abaixo cria dois componentes e usa eles.

// Cria um componente Title, um h1 com estilos
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

// Cria um componente Wrapper, uma section estilizada
const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

// Use-os como você usaria qualquer outro componente
render(
  <Wrapper>
    <Title>Hello World!</Title>
  </Wrapper>
);

🔥 Detalhe! O css gerado já tem os prefixos de navegadores. Vai em frente, usa todas as propriedades hipsters que você conhece ;)

Adaptando os componentes com base em props

O styled-components gera um componente, certo? Se gera um componente, pode ter props. E se tem props, você pode usar.

Esse exemplo abaixo tem um estado primary que muda as cores com base na presença (ou ausência) da prop. Para isso, basta usar a famosa interpolação ;)

const Button = styled.button`
  background: ${(props) => (props.primary ? 'palevioletred' : 'white')};
  color: ${(props) => (props.primary ? 'white' : 'palevioletred')};

  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

render(
  <div>
    <Button>Normal</Button>
    <Button primary>Primary</Button>
  </div>
);

Estendendo estilos

Às vezes precisamos fazer pequenas adaptações no layout de um componente. Com o styled-components, basta envolvê-lo no construtor styled:

// Botão do exemplo acima, sem as interpolações
const Button = styled.button`
  color: palevioletred;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

// Um novo Botão, baseado no anterior, com alguns detalhes a mais
const TomatoButton = styled(Button)`
  color: tomato;
  border-color: tomato;
`;

render(
  <div>
    <Button>Normal Button</Button>
    <TomatoButton>Tomato Button</TomatoButton>
  </div>
);

Ainda, é possível substituir o elemento gerado. Por exemplo, se quiséssemos que, ao invés de um button, nosso componente TomatoButton /> gerasse um a, é só fazer:

<Button as='a' href='/'>
  Link com estilos de Button
</Button>

📚 Leitura recomendada: Talia Marcassa escreveu uma ótima revisão do uso no mundo real, apresentando muitos insights práticos sólidos e comparações com alternativas, em Styled Components: To Use or Not to Use?

Sintaxe

O styled-components usa um pré-processador chamado stylis, que suporta a sintaxe do SCSS.

const Thing = styled.div.attrs((/* props */) => ({ tabIndex: 0 }))`
  color: blue;

  &:hover {
    color: red; // <Thing> quando passamos o mouse
  }

  & ~ & {
    background: tomato; // <Thing> como irmão de <Thing>, mas talvez não diretamente adjacente
  }

  & + & {
    background: lime; // <Thing> adjacente a <Thing>
  }

  &.something {
    background: orange; // <Thing> tagueado com uma classe CSS adicional ".something"
  }

  .something-else & {
    border: 1px solid; // <Thing> dentro de outro elemento nomeado ".something-else"
  }
`;

render(
  <React.Fragment>
    <Thing>Hello world!</Thing>
    <Thing>How ya doing?</Thing>
    <Thing className='something'>The sun is shining...</Thing>
    <div>Pretty nice day today.</div>
    <Thing>Don't you think?</Thing>
    <div className='something-else'>
      <Thing>Splendid.</Thing>
    </div>
  </React.Fragment>
);

Anexando props adicionais

Para evitar wrappers desnecessários que apenas passam algumas props para o componente ou elemento renderizado, você pode usar o construtor .attrs. Ele permite que você anexe props adicionais (ou "atributos") a um componente. Dessa forma, você pode, por exemplo, anexar props estáticas a um elemento ou passar uma prop de terceiros como activeClassName para o componente Link do React Router. Além disso, você também pode anexar props mais dinâmicas a um componente. O objeto .attrs também pode receber funções, que recebem as props que o componente recebe. O valor de retorno será mesclado com os props resultantes também.

Aqui, renderizamos um componente input e anexamos alguns atributos dinâmicos e estáticos a ele:

const Input = styled.input.attrs((props) => ({
  // podemos definir props estáticas
  type: 'text',

  // ou definir props dinâmicas
  size: props.size || '1em',
}))`
  color: palevioletred;
  font-size: 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;

  /* aqui usamos a prop computada dinamicamente */
  margin: ${(props) => props.size};
  padding: ${(props) => props.size};
`;

render(
  <div>
    <Input placeholder='Um input pequeno' />
    <br />
    <Input placeholder='input maior' size='2em' />
  </div>
);

Animações

Por fim, vamos dar aquela animada nos nossos componentes? Animações CSS definidas com @keyframes são globais, e isso pode levar a colisão de nomes. O styled-components fornece um helper para mitigar esse problema:

// Criar a animação
const rotate = keyframes`
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
`;

// Criar um componente que vai rotacionar o que receber
const Rotate = styled.div`
  display: inline-block;
  animation: ${rotate} 2s linear infinite;
  padding: 2rem 1rem;
  font-size: 1.2rem;
`;

render(
  <Rotate> < 💅🏾 > </Rotate>
);

⚠️ Keyframes não é suportada pelo React Native.


Referências

Conceitos

Bibliotecas


Ir para Próxima Seção

Made with 💜