Componente Snackbar com React do zero
Tags: react, frontend, javascript, css
Published: 2021-01-28 02:28:57

Componentes snackbar são aqueles alertas flutuantes com informações importantes, ex: mensagens de erro, alertas, sucesso etc. 
Utilizando React podemos criar um snackbar de forma bem simples.

## Vamos ao código

Na raiz do projeto crie uma pasta chamada **components** e dentro desta, uma outra chamada **Snackbar**.

Dentro da pasta **Snackbar** crie os arquivos *index.js* e *styles.css*.

No arquivo index vamos criar um functional component com o JSX inicial do nosso snackbar.

```jsx
import React from "react";
import "./styles.css";

export default function Snackbar() {
  return (
    <div className="snackbar visible success">
      <span>Lorem ipsum dolor sit amet</span>
      <button className="close">x</button>
    </div>
  );
}
```

Vamos adicionar alguns estilos para deixar nosso snackbar bonitão quando ele aparecer na tela.

```css
.snackbar {
  background-color: #333;
  position: fixed;
  bottom: 0;
  left: 50%;
  width: 400px;
  margin-left: -200px;
  opacity: 0;
  visibility: hidden;
  color: #fff;
  padding: 16px;
  border-radius: 4px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: all 200ms ease-in-out;
}

.snackbar .close {
  font-size: 18px;
  cursor: pointer;
  transition: 200ms;
  padding: 0;
  border: 0;
  background-color: transparent;
  color: #fff;
}
```

Vamos adicionar algumas propriedades para nosso componente e começar a trabalhar na lógica de exibir e ocultar.

```jsx
function Snackbar({ type, open, children, onClose }) {
  return (
    <div className={`snackbar ${open && "visible"} ${type}`}>
      <span>{children}</span>
      <button className="close" onClick={onClose}>
        &times;
      </button>
    </div>
  );
}
```

Note as props **open** e **type**, essas serão essencialmente usadas para adicionar os estilos principais da snackbar e também exibir e ocultar.

```jsx
className={`snackbar ${open && "visible"} ${type}`}
```

Quando a prop **open** for *true* a classe *.visible* será adicionada ao componente. Então basta adicionar visibilidade ao componente via CSS.

```css
.snackbar.visible {
  opacity: 1;
  bottom: 20px;
  visibility: visible;
}
```

a prop **type** receberá valores como success, error, warning e info. Podemos usar cada um desses valores para adicionar uma cor diferente ao snackbar.

```css
.snackbar.success {
  background-color: rgb(0, 158, 0);
}

.snackbar.info {
  background-color: rgb(86, 83, 255);
}

.snackbar.warning {
  background-color: rgb(255, 181, 44);
}

.snackbar.error {
  background-color: rgb(219, 55, 55);
}
```

> Obs: Para lidar com o bind dinâmico de classes poderíamos usar uma lib como [classnames](https://www.npmjs.com/package/classnames), mas como se trata de uma lógica bem simples, vamos fazer isso sem lib mesmo.

## Toques finais
Apesar de ser um componente pequeno (400px). Para garantir a boa visualização em telas pequenas, vamos fazer um pequeno ajuste usando @media querie.
```css
@media (max-width: 480px) {
  .snackbar {
    width: 100%;
    margin-left: 0;
    left: 0;
    border-radius: 4px 4px 0 0;
  }

  .snackbar.visible {
    bottom: 0;
  }
}
```

Agora sim, nosso componente está pronto para uso.

```jsx
<Snackbar
  type="success"
  open={someStateOpen}
  onClose={() => setSomeStateOpen(false)}
>
  Que snackbar massa e fácil de usar =)
</Snackbar>
```

Acesse [a demo no codesandbox](https://codesandbox.io/s/snackbar-cdntc?file=/src/App.js:495-676) para conferir o código completo e exemplo de uso.