FrontEndMentor.io Challenge #2
Tags: react, styledcomponents, frontendmentor
Published: 2021-09-10 22:45:40

Continuando os meus estudos semanais, iniciei a semana da independência apenas após o feriado, no dia 08 de setembro (🖕 FORA BOLSONARO 🖕). Por ser uma semana menor, escolhi um desafio um pouco mais simples, desta vez focado em responsividade. O desafio escolhido foi o [Sunnyside agency landing page](https://www.frontendmentor.io/challenges/sunnyside-agency-landing-page-7yVs3B6ef), um projeto bem colorido e divertido de se fazer. 

##Briefing

Desta vez o projeto não tem nenhuma API para ser consumida, são apenas textos e imagens estáticas renderizadas na tela. O desafio é uma *landing page*, bem colorida e cheia de imagens. O seu design todo *quadradão* parece ser perfeito para exercitar conceitos de responsividade. 

Assim como todos os desafios do FronEndMentor que fiz até então (tanto os quais eu já escrevi aqui, quanto os quais ainda irei escrever), este também foi desenvolvido para dispositivos *mobile* de 375px, quanto para telas de *desktop* de 1440px.

##Tools

Aqui fiquei em dúvida sobre qual tecnologia usar, SASS me pareceu uma boa escolha, mas no final acabei indo, *por força do hábito*, de styled-components 💅 hahah.

##O projeto

Inicie o projeto com CRA + typescript. Tenho usado TS em todos os projetos, até nos mais simples. No final das contas, mal não vai fazer *espero*. 

Após aquela limpeza básica nos arquivos, instalei o styled-components, e já fui logo escrevendo. Assim como meus últimos projetos, optei por iniciar pela versão mobile, e meu primeiro componente aqui foi o `<Header />`. Ele foi bem simples de fazer, pois é apenas uma logo em svg, e alguns `<a>`. Para fazer o *Hamburger Menu* eu uso um snippet que criei que basicamente é isso aqui: 
```
  <input type="checkbox" id="menu_hamburger" />
  <label htmlFor="menu_hamburger">
    <img src="/icon-hamburger.svg" alt="menu" />
  </label>
``` 
No CSS eu deixo o `<input>` invisível com `display: none` e `visibility: hidden`. A `<label>` aqui vai ser o ícone do menu, e ao mesmo tempo vai servir para *marcar* ou *desmarcar* o `<input>`. Abaixo desse código entra a `<nav>`, que em um primeiro momento também vai estar invisível, usando as mesmas propriedades já mostradas ali em cima. Para torná-la visível, eu uso o seletor *checked* do input, desta forma: 

```
  input:checked ~ nav {}
```

Então, quando o input não estiver marcado, apenas a logo e o icone do *Hamburger Menu*, ao ser marcado o menu flutuante aparece. Simples né?! Eu poderia fazer a mesma coisa usando o `useState()` do React, mas acho que pesaria mais do que simplesmente usar CSS. 

Além do `<Header>`, na página inicial temos a imagem de uma laranja gigante, que ocupa a tela toda, como se fosse um background. No entanto, não usei ela como background, mas sim como um `<img>`, pois neste ponto notei que quase todas as imagens tinham versões otimizadas(??) para cada tipo de tela. Ao longo do texto vou falar melhor sobre como optei para identificar o tamanho da tela do usuário e usar a imagem mais adequada para cada tipo.

Com a `<img>` já em tela, dei a ela `position: absolute` e `z-index: -1` para jogar ela para de baixo de tudo na tela inicial. Com mais um `<h1>` a tela inicial já estava pronta e funcional.

A próxima parte é composta por uma imagem seguida de uma `<div>` com um título e texto. Aqui já tinha noção que na versão *desktop* a ordem de exibição estaria "invertida" em relação a versão *mobile*, além de ser exibida na horizontal. Para resolver isso coloquei a `<div>` seguido da `<img>` e usei o código CSS a seguir:

```
  display: flex;
  flex-direction: column-reverse;
  align-items: center;
  justify-content: center;
```   

Assim, quando fosse para versão desktop seria apenas colocar `flex-direction: row` e já estaria tudo pronto. Poderia ter feito o inverso também, aplicando reverse-row na versão desktop futuramente. E com isso já tinha matado duas seções. Na verdade quase três, pois o próximo componente, que faria apenas no dia seguinte, teria a mesma estrutura que esse último. 

No dia seguinte, 09/09, não tive problemas para fazer o terceiro componente, e nem os demais. Em um componente que chamei de `<Gallery />`, deveria ser exibido quatro imagens, duas em cima e duas em baixo, na versão *mobile*, e as quatro uma ao lado da outra na versão *desktop*, meu primeiro pensamento foi usar grid, mas achei que seria mais fácil usar  flexbox, da seguinte forma: 

```
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
```
Definindo a largura de cada imagem em 50% em relação a tela, assim quando fosse para a versão *desktop* seria apenas usar `flex-wrap: nowrap` para deixá-las na horizontal. Nesse dia demorei mais tentando descobrir as medidas de `padding` e `margin` no Photoshop do que outra coisa hahaha. Essas propriedades só são disponibilizadas para quem paga o premium do site, através do Figma ou Sketch.

Ao começar a fazer o `<Footer />` percebi que uma das cores apontadas no *style-guide* do projeto estava bem longe do que deveria ser, então usei o conta gotas do PS para identificar a cor real do projeto. Resolvi falar sobre isso aqui porque vários outros projetos vieram com cores erradas ou cores faltando, esse não foi diferente 🙄 (mas como é de graça né). 

O projeto original também disponibilizou logos de redes sociais em .svg, mas optei por usar o react-icons, pois fica mais fácil de trabalhar *active states*, como *hover* por exemplo. 

Foi no footer onde tive meu primeiro problema, a logo disponibilizada veio em svg e na cor branca, porém no footer deveria dar outra cor para ela. Eu sei que posso usar jQuery para achar a tag img e buscar a propriedade *fill* dentro do svg, porém fiz da forma mais fácil aqui hihihi 😛 usei o svg *inline*, e mudei manualmente a cor de preenchimento dele. 

Com isso já estava pronto a versão mobile, e mais um dia havia se encerrado. 

No último dia de projeto, precisava apenas terminar os ajustes para versão desktop, o que não foi nada difícil (já falei sobre os principais ajustes ao longo do texto). Quero destacar como fiz para escolher qual versão da imagem usar de acordo com cada tamanho de tela. 

Todos os meus componentes foram agrupados no `App.tsx`, assim, neste documento criei um state para guardar a largura da tela, desta forma `const [screenWidth, setScreenWidth] = useState(0)`. Para pegar a largura da tela usei o seguinte código: 

```
  window.onresize = () => {
    const w = document.body.clientWidth
    setWidth(w)
  }
```
Assim, cada vez que a tela é redimencionada, é definido um novo valor para `width`, essa variável foi passada como uma prop para cada um dos componentes que contenham imagens. Dentro de cada componente fiz uma verificação ternária dentro do return para exibir a imagem correta, assim ó:

```
...code
return (
  {width <= 700
   ? <img src="/mobile/image.jpg" alt="blah" />
   : <img src="/desktop/image.jpg" alt="blah" />
  }
)
```
***Não use blah no alt das `<img>` caga com a acessibilidade da aplicação - aqui é apenas um exemplo. 

E assim se encerrou mais um projetinho do FrontEndMentor. Ah! hoje 10/09 realizei minha inscrição para a #nextjsconf da 
[@vercel](https://twitter.com/vercel), que será realizada mais para o final de outubro. 

Github do projeto: https://github.com/GuihLeme/sunnyside-landing-page
Site: https://sunnyside-landing-page-pi.vercel.app/