Criando extensões para o Google Chrome com React
Tags: react, chrome, google, braziliandevs
Published: 2021-02-02 02:48:31

Talvez não seja algo tão conhecido, mas extensões para o Google chrome são desenvolvidos com tecnologias web (Javascript, Html e Css). 
Dessa forma, é totalmente possível utilizarmos o React (assim como outra lib/framework frontend) para criar extensões.
Nesse post, vou mostrar como criar uma extensão bem legal usando o React! 
Sem mais delongas, vamos por a mão na massa.

## Índice 📖
 * [ O projeto 📝 ](#o-projeto)  
 * [ Configurando o projeto ⚙ ](#configurando-o-projeto-%E2%9A%99)  
 * [ Iniciando com React ⚛️ ](#iniciando-com-react)  
   * [ Criando componente de item 🧱 ](#criando-componente-de-item)  
   * [ Criando componente de lista 📄 ](#criando-componente-de-lista)  
   * [ Gerenciando estado das tasks 🔮 ](#gerenciando-estado-das-tasks)  
   * [ Criando botão de ação (FAB) 🎬 ](#criando-bot%C3%A3o-de-a%C3%A7%C3%A3o-fab)  
   * [ Criando Modal para adicionar tasks ❎ ](#criando-modal-para-adicionar-tasks)  
   * [ Adicionando tasks ao estado 🔩 ](#adicionando-tasks-ao-estado)  
   * [ Melhorias 🔝 ](#melhorias)  
   * [ Criando Modal de concluir task ✅ ](#criando-modal-de-concluir-task)  
   * [ Finalizando App React 🙅‍♂️ ](#finalizando-app-react)  
 * [ Transformando o app em extensão 🌠 ](#transformando-o-app-em-extens%C3%A3o)  
 * [ Conclusão 🎯 ](#conclus%C3%A3o) 
 
###### generated with [Summaryze DEV](https://summaryze-dev.vercel.app/)

## O projeto 📝 <a name="o-projeto"></a>

Vamos fazer uma extensão simples, um app de TODO. 
Vamos poder adicionar tarefas, listar as tarefas e marca-las como concluída.
![Previa do app](https://dev-to-uploads.s3.amazonaws.com/i/xbw9biweo1a4wddcgsau.gif)

## Configurando o projeto ⚙ <a name="configurando"></a>
Vamos começar iniciando um projeto [React](https://pt-br.reactjs.org/), vamos utilizar o [CRA](https://pt-br.reactjs.org/docs/create-a-new-react-app.html) para iniciar nosso projeto, então vamos começar com comando:
```bash
npx create-react-app todo-chrome
```
Com a estrutura básica criada pelo CRA, vamos instalar algumas dependências, vou utilizar o Material UI para esse projeto, então vamos adiciona-lo como dependência do nosso projeto junto com os ícones:
```bash
yarn add @material-ui/core @material-ui/icons
#ou
npm install @material-ui/core @material-ui/icons
```
Agora vamos adicionar a fonte, podemos adiciona-la utilizando CDN ou como dependência do projeto, nesse caso, vou utilizar CDN, então, no `index.html` dentro da pasta `public` vamos adicionar essa tag dentro do `<header>`:
```html
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
```
## Iniciando com React ⚛️ <a name="iniciando-react"></a>
Com tudo instalado e configurado, vamos a estrutura do projeto. Aqui não é algo que influencia diretamente no "produto final", portanto, se você estiver acostumado com outra estrutura, pode segui-la, a minha ficou da seguinte forma:
![Estrutura de pastas do projeto](https://dev-to-uploads.s3.amazonaws.com/i/11sds99wp4izuzguk8ut.png)

Vamos iniciar o desenvolvimento real do nosso app, vamos criar e editar um arquivo `index.jsx` dentro da pasta `src/pages/home` e vamos começar a estrutura visual do nosso app. 
Antes não esqueça de importar o componente e chama-lo no `App.js` para poder renderiza-lo na tela. 
Todo o desenvolvimento vai ser de um app react "normal", então vamos utilizar o hot reload para nos auxiliar durante o desenvolvimento. 
Uma pequena observação é sobre o tamanho da aplicação (altura X largura), tendo em vista que é uma extensão, elas não costumam tomar muito espaço, então criei um arquivo chamado `global.css` e nele coloquei uma altura e largura fixa, além de algumas outras estilizações e importei no  o arquivo no `index.js`:

```css
/* global.css */

body {
  width: 350px;
  height: 500px;
  background-color: #ccc;
}

#root {
  height: 100%;
}

.App {
  font-family: "Roboto";
  height: 100%;
  background-color: #ccc;
  overflow-y: scroll;
}

.container {
  position: relative;
  min-height: 100%;
}

.finished {
  text-decoration: line-through;
  opacity: 0.6;
}

.no-tasks {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  width: 100%;
  height: 450px;
}

* {
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 0, 0, 0.2) rgba(0, 0, 0, 0.2);
}

*::-webkit-scrollbar {
  width: 4px;
}

*::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.2);
}

*::-webkit-scrollbar-thumb {
  background-color: rgba(0, 0, 0, 0.2);
  border-radius: 20px;
  border: 20px solid rgba(0, 0, 0, 0.2);
}
```
No `index.js` ficou assim:
```javascript
// index.js
import React from "react";
import ReactDOM from "react-dom";
import "./assets/global.css";
import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

```
### Criando componente de item 🧱 <a name="componente-item"></a>
Agora, podemos voltar a atenção para a pagina `home`.
Vou começar criando meu componente de item, que será a tarefa que vamos mostrar na lista, para isso, vou criar uma pasta chamada `components` dentro da pasta `home`, e vou criar um arquivo chamado `Item.List.jsx`. Nele vou importar alguns componentes do Material UI e teremos o seguinte resultado:
![Componente de item da lista](https://dev-to-uploads.s3.amazonaws.com/i/g8uyoaqn70a0qsnphpa0.png)

Nosso arquivo ficará assim:
```javascript
import React from "react";
import { Box, Paper, Grid } from "@material-ui/core";
import { DateRange, AccessTime } from "@material-ui/icons";

function randomColor() {
  const colors = ["#eb4034", "#B8FF33", "#33FFA8", "#7B5EBF"];

  return colors[Math.floor(Math.random() * (colors.length - 1)) + 1];
}

function ItemList() {
  return (
    <Box
      paddingLeft={0.5}
      borderRadius={4}
      style={{ backgroundColor: randomColor() }}
    >
      <Paper style={{ minHeight: 60, padding: 10, paddingTop: 1 }}>
        <h3>Teste de todo para design</h3>
        <Grid container justify="space-between">
          <Grid>
            <small>
              <Grid container justify="center" alignItems="center">
                <DateRange fontSize="small" /> 01/01/2020
              </Grid>
            </small>
          </Grid>
          <Grid>
            <small>
              <Grid container justify="center" alignItems="center">
                <AccessTime fontSize="small" />
                10 minutos atrás
              </Grid>
            </small>
          </Grid>
        </Grid>
      </Paper>
    </Box>
  );
}

export default ItemList;
```
### Criando componente de lista 📄 <a name="componente-lista"></a>
Agora vamos criar o nosso componente de lista, que será responsável por receber os itens a serem renderizados e chamar um `ItemList` pra cada um deles, crie um componente ainda na pasta `components` dentro de `src/pages/home` e chame-o de `List.jsx`, seu conteúdo inicialmente ficará da seguinte forma:
```javascript
import React from "react";
import { Box } from "@material-ui/core";

import ItemList from "./Item.List";

function List() {
  return (
    <Box padding={1}>
      <ItemList />
    </Box>
  );
}

export default List;
```
Basicamente importamos nosso item e exibimos ele dentro do componente de lista. 
O que precisamos fazer agora é receber via props as nossas tarefas, percorre-las e passar as informações para nosso item, e vamos fazer isso assim:
```javascript
...
function List({ tasks }) {
  return (
    <Box padding={1}>
      {tasks && tasks.map((task) => <ItemList task={task} />)}
    </Box>
  );
}
...
```
Agora vamos modificar o nosso `Item.List.jsx` para receber a prop task e criar um callback para quando ele for clicado. Ficando dessa forma:
```javascript
...
function ItemList({ task, onClick }) {
  return (
    <Box
      paddingLeft={0.5}
      borderRadius={4}
      style={{ backgroundColor: randomColor() }}
      onClick={() => onClick(task.id)}
    >
      <Paper style={{ minHeight: 60, padding: 10, paddingTop: 1 }}>
        <h3>{task.title}</h3>
        <Grid container justify="space-between">
          <Grid>
            <small>
              <Grid container justify="center" alignItems="center">
                <DateRange fontSize="small" /> {task.date}
              </Grid>
            </small>
          </Grid>
          <Grid>
            <small>
              <Grid container justify="center" alignItems="center">
                <AccessTime fontSize="small" />
                {task.time}
              </Grid>
            </small>
          </Grid>
        </Grid>
      </Paper>
    </Box>
  );
}
...
```
Agora no nosso `List.jsx`, vamos receber esse callback e por enquanto, vamos apenas disparar um alert. 
Outra modificação para fazermos nesse componente é adicionar uma mensagem de "Sem tarefas" quando o array estiver vazio, ficando assim:
```javascript
...
function List({ tasks }) {
  function handleItemClick(id) {
    alert(`Clicou no item ${id}`);
  }

  return (
    <Box padding={1}>
      {tasks &&
        tasks.map((task) => <ItemList task={task} onClick={handleItemClick} />)}

     {tasks.length === 0 && (
        <div className="no-tasks">
          <span>Sem tarefas, crie uma agora mesmo!</span>
        </div>
      )}
    </Box>
  );
}
...
```
### Gerenciando estado das tasks 🔮 <a name="gerenciando-tasks"></a>
Voltando ao nosso componente da Home page, vamos fazer nosso gerenciamento de tasks utilizando o `hook` de estado do React, o que vai deixar tudo super simples e eficiente, vamos começar declarando um novo estado para as nossas tarefas e inicializa-las como um array vazio, em seguida vamos passar esse estado na prop da nossa lista:
```javascript
// src/pages/home/index.jsx
import React, { useState } from "react";

import List from "./components/List";

function HomePage() {
  const [tasks, setTasks] = useState([]);

  return <List tasks={tasks} />;
}

export default HomePage;
```
### Criando botão de ação (FAB) 🎬 <a name="criando-fab"></a>
Agora vamos criar um `float action button` para adicionar novas tarefas quando clicarmos nele e em seguida vamos criar um modal com um campo de texto para o usuário digitar o titulo da tarefa. 
Vamos importar o `FAB` e um ícone do Material UI e colocar junto com a nossa lista no componente da tela inicial, ambos envolvidos por uma div com uma class:

```javascript
import React, { useState } from "react";
import { Fab } from "@material-ui/core";
import { Add } from "@material-ui/icons";
import List from "./components/List";

function HomePage() {
  const [tasks, setTasks] = useState([]);

  return (
    <div class="container">
      <List tasks={tasks} />
      <Fab
        color="primary"
        style={{ position: "absolute", bottom: "30px", right: "10px" }}
      >
        <Add />
      </Fab>
    <div/>
  );
}

export default HomePage;

```
O resultado até agora é esse:
![Previa do app](https://dev-to-uploads.s3.amazonaws.com/i/x7ekyj374r70gcbr44n4.png)

### Criando Modal para adicionar tasks ❎ <a name="modal-tasks"></a>
Vamos criar uma modal com dois botões e um input para o usuário poder digitar o titulo da tarefa, porém, não vamos usar o componente `Modal` do Material UI e sim o componente `Dialog`, então vou criar um novo componente chamado `Modal.NewTask.jsx` dentro da pasta `src/pages/home/components` e vamos por o seguinte conteúdo:
```javascript
import React, { useState } from "react";
import {
  Dialog,
  DialogActions,
  DialogContent,
  DialogContentText,
  DialogTitle,
  TextField,
  Button,
} from "@material-ui/core";

function NewTaskModal({ show, onClose, onAdd }) {
  const [taskName, setTaskName] = useState("");

  function addNewTask() {
    onAdd(taskName);
    setTaskName("");
    onClose();
  }

  return (
    <Dialog open={show} onClose={onClose} aria-labelledby="form-dialog-title">
      <DialogTitle id="form-dialog-title">
        Adicionar uma nova tarefa
      </DialogTitle>
      <DialogContent>
        <DialogContentText>
          Insira o nome da tarefa que deseja inserir
        </DialogContentText>
        <TextField
          id="task_name"
          autoFocus
          margin="dense"
          label="Titulo da tarefa"
          type="text"
          fullWidth
          value={taskName}
          onChange={(e) => setTaskName(e.target.value)}
        />
      </DialogContent>
      <DialogActions>
        <Button onClick={onClose} color="secondary">
          Cancelar
        </Button>
        <Button onClick={addNewTask} color="primary">
          Adicionar
        </Button>
      </DialogActions>
    </Dialog>
  );
}

export default NewTaskModal;
```
Visualmente nosso modal ficou assim:
![Previa modal de adicionar tarefa](https://dev-to-uploads.s3.amazonaws.com/i/jnyhah35q2gdskida6kq.png)
Ficou um componente bem grande, principalmente por causa da estrutura do `Dialog` do Material UI, mas aqui tem algumas coisas acontecendo que vou explicar. A primeira coisa a se observar são as três props que recebemos: `show`, `onClose` e `onAdd`, elas são respectivamente: uma variável que controla se exibe ou não a modal, uma função para fechar a modal(clicando fora ou cancelando) e uma função para adicionar a nova tarefa quando clicar no botão `Adicionar`.
Ainda no Modal, temos um hook de estado para gerenciar o que está sendo digitado no campo de texto e temos uma função `addNewTask`, que: chama uma função de callback, limpa o texto do campo e fecha a modal. 
Agora, vamos importar esse componente também na nossa tela inicial, ficando assim:
```javascript
...
import NewTaskModal from "./components/Modal.NewTask";
...
function HomePage() {
...
const [showNewTaskModal, setNewTaskModal] = useState(false);

  function handleNewTask(taskName) {
    alert(`Nova tarefa: ${taskName}`);
  }

return (
...
  <NewTaskModal
        show={showNewTaskModal}
        onClose={() => setNewTaskModal(false)}
        onAdd={handleNewTask}
      />
)
...
```
Importamos nossa modal, usamos um hook para gerenciar o estado dela e declaramos uma função que por enquanto, apenas exibe um alert com o que o usuário digitou. Agora vamos exibir nossa Modal quando o usuário clicar no nosso FAB:
```javascript
// src/pages/home/index.jsx

...
<Fab
        color="primary"
        style={{ position: "absolute", bottom: "30px", right: "30px" }}
        onClick={() => setShowModal(true)}
      >
...
```
### Adicionando tasks ao estado 🔩 <a name="tasks-estado"></a>
Vamos deixar tudo mais interessante agora que vamos adicionar a nova task a nosso estado para que ela seja renderizada na nossa lista, para isso, vamos precisar pegar além do titulo da tarefa, uma data, hora e gerar um id.
Vou criar uma função para gerar IDs em um arquivo na pasta `utils` e chama-lo de `IdGenerator.js`, seu conteúdo ficará o seguinte:
```javascript
function generateId() {
  return "_" + Math.random().toString(36).substr(2, 9);
}

export default generateId;
```
Vou importar minha função de gerar id na minha pagina inicial e vou implementar minha criação de tarefas, ficando assim a minha função `handleNewTask()`:
```javascript
...
  function handleNewTask(taskName) {
    const newTask = {
      id: generateId(),
      title: taskName,
      date: new Date().toDateString(),
      time: new Date().toDateString(),
    };

    setTasks([...tasks, newTask]);
  }
...
```
Com essa função implementada, já é possível criar uma nova tarefa:
![App com tarefa criada](https://dev-to-uploads.s3.amazonaws.com/i/6szybb7do8j5agisgng9.png)
E se clicarmos em um item:
![Mensagem após clicar em uma tarefa](https://dev-to-uploads.s3.amazonaws.com/i/nmks4dn5qhg1d7is1nna.png)
### Melhorias 🔝 <a name="melhorias"></a>
Bem legal o funcionamento até aqui, uma melhoria é na data e no horário, estamos exibindo o objeto `Date` direto, sem formatação, e podemos melhorar isso, para formatar vamos usar o [date-fns](https://date-fns.org/), uma biblioteca javascript que manipula datas e horários de forma super simples e vai nos ajudar principalmente para exibir o horário no formato que queremos (X minutos/horas atrás). Então, instale o date-fans:
```bash
yarn add date-fns
#ou
npm install date-fns
```
E dentro do nosso componente de Item vamos modificar onde exibimos a data e hora, vamos importar as funções `format()` e `formatDistance()` e o objeto de idioma em português `ptBR`, então, vamos atualizar nosso `Item.List.jsx`:
```javascript
import React from "react";
import { Box, Paper, Grid } from "@material-ui/core";
import { DateRange, AccessTime } from "@material-ui/icons";
import { format, formatDistance } from "date-fns";
import { ptBR } from "date-fns/locale";

function randomColor() {
  const colors = ["#eb4034", "#B8FF33", "#33FFA8", "#7B5EBF"];

  return colors[Math.floor(Math.random() * (colors.length - 1)) + 1];
}

function ItemList({ task, onClick }) {
  return (
    <Box
      paddingLeft={0.5}
      marginTop={1}
      borderRadius={4}
      style={{ backgroundColor: randomColor() }}
      onClick={() => onClick(task.id)}
    >
      <Paper style={{ minHeight: 60, padding: 10, paddingTop: 1 }}>
        <h3>{task.title}</h3>
        <Grid container justify="space-between">
          <Grid>
            <small>
              <Grid container justify="center" alignItems="center">
                <DateRange fontSize="small" /> {format(task.date, "dd/MM/yyyy")}
              </Grid>
            </small>
          </Grid>
          <Grid>
            <small>
              <Grid container justify="center" alignItems="center">
                <AccessTime fontSize="small" />
                {formatDistance(task.date, new Date(), {
                  locale: ptBR,
                })}
              </Grid>
            </small>
          </Grid>
        </Grid>
      </Paper>
    </Box>
  );
}

export default ItemList;
```
Perceba que estamos usando o `task.date` tanto para a data quanto para a hora, então na nossa home podemos remover a propriedade `time` e vamos remover o `toDateString()` que temos no date também. Ficando dessa forma:
```javascript
 function handleNewTask(taskName) {
    const newTask = {
      id: generateId(),
      title: taskName,
      date: new Date(),
    };

    setTasks([...tasks, newTask]);
  }
```
E aqui está nosso resultado até aqui:
![Item da lista com data e hora correta](https://dev-to-uploads.s3.amazonaws.com/i/mg9z86as71ufr9zjfhis.png)
### Criando Modal de concluir task ✅ <a name="modal-concluir"></a>
Agora vamos fazer criar uma modal para quando o usuário clicar para marcar a task como finalizada. 
Para isso vamos começar criando um novo componente chamado `Modal.ChangeTaskStatus.jsx` e como conteúdo vamos ter:
```javascript
import React from "react";
import {
  Dialog,
  DialogActions,
  DialogContent,
  DialogContentText,
  DialogTitle,
  Button,
} from "@material-ui/core";

function ModalChangeStatus({ show, onClose, onSave, taskToEdit }) {
  function finishTask() {
    onSave(taskToEdit.id);
    onClose();
  }

  return (
    <Dialog open={show} onClose={onClose} aria-labelledby="form-dialog-title">
      <DialogTitle id="form-dialog-title">Concluir tarefa</DialogTitle>
      <DialogContent>
        <DialogContentText>
          Deseja marcar a tarefa "{taskToEdit.title}" como concluida ?
        </DialogContentText>
      </DialogContent>
      <DialogActions>
        <Button onClick={onClose} color="secondary">
          Cancelar
        </Button>
        <Button onClick={finishTask} color="primary">
          Concluir
        </Button>
      </DialogActions>
    </Dialog>
  );
}

export default ModalChangeStatus;
```
Agora vamos importar isso na nossa tela inicial, criar dois novos hooks de estado, um para gerenciar a visibilidade da modal e outro para "segurar" o item que será editado. 
As modificações são:
```javascript
...
import EditTaskModal from "./components/Modal.ChangeTaskStatus";
...
const [taskToEdit, setTaskToEdit] = useState("");
const [showEditModal, setShowEditModal] = useState(true);

...
     <EditTaskModal
        show={showEditModal}
        onClose={() => setShowEditModal(false)}
        onSave={handleUpdateTask}
        taskToEdit={taskToEdit}
      />
...
```
Agora podemos chamar nossa modal toda vez que clicarmos em um item da lista, porém, vamos precisar refatorar uma pequena parte no nosso componente de lista, vamos remover nossa função `handleItemClick()` e vamos receber ela via props:
```javascript
import React from "react";
import { Box } from "@material-ui/core";

import ItemList from "./Item.List";

function List({ tasks, handleItemClick }) {
  return (
    <Box padding={1}>
      {tasks &&
        tasks.map((task) => <ItemList task={task} onClick={handleItemClick} />)}

      {tasks.length === 0 && (
        <div className="no-tasks">
          <span>Sem tarefas, crie uma agora mesmo!</span>
        </div>
      )}
    </Box>
  );
}

export default List;
```
E na nossa tela inicial, podemos passar uma função que vai receber o id clicado, vamos buscar esse id no nosso estado e em seguida chamar a função para mudar o status passando o item completo, vamos implementar também a função que atualiza no estado o status do item, o que significa que também vamos refatorar a função de criação da tarefa, adicionando a propriedade `status` a ela, o que vai deixar nossa pagina inicial assim:

```javascript
import React, { useState } from "react";
import { Fab } from "@material-ui/core";
import { Add } from "@material-ui/icons";
import List from "./components/List";
import generateId from "../../utils/IdGenerator";
import NewTaskModal from "./components/Modal.NewTask";
import EditTaskModal from "./components/Modal.ChangeTaskStatus";

function HomePage() {
  const [tasks, setTasks] = useState([]);
  const [taskToEdit, setTaskToEdit] = useState();
  const [showNewTaskModal, setNewTaskModal] = useState(false);
  const [showEditModal, setShowEditModal] = useState(false);

  function handleNewTask(taskName) {
    const newTask = {
      id: generateId(),
      title: taskName,
      date: new Date(),
      status: "enabled",
    };

    setTasks([...tasks, newTask]);
  }

  function handleUpdateTask(id) {
    const taskIndex = tasks.findIndex((task) => task.id === id);

    if (taskIndex === -1) {
      return;
    }

    const tasksCopy = [...tasks];
    const taskUpdate = { ...tasks[taskIndex] };
    
    taskUpdate.status = "disabled";
    tasksCopy[taskIndex] = taskUpdate;

    setTasks(tasksCopy);
  }

  function handleItemClick(id) {
    const itemToEdit = tasks.find((task) => task.id === id);

    if (!itemToEdit) {
      return;
    }

    setTaskToEdit(itemToEdit);
    setShowEditModal(true);
  }

  return (
    <div class="container">
      <List tasks={tasks} handleItemClick={handleItemClick} />
      <Fab
        color="primary"
        style={{ position: "absolute", bottom: "30px", right: "30px" }}
        onClick={() => setNewTaskModal(true)}
      >
        <Add />
      </Fab>

      <NewTaskModal
        show={showNewTaskModal}
        onClose={() => setNewTaskModal(false)}
        onAdd={handleNewTask}
      />

      <EditTaskModal
        show={showEditModal}
        onClose={() => setShowEditModal(false)}
        onSave={handleUpdateTask}
        taskToEdit={taskToEdit}
      />
    </div>
  );
}

export default HomePage;
```
### Finalizando App React 🙅‍♂️ <a name="finalizando-react"></a>
E vamos precisar adicionar um pequeno detalhe no nosso `Item.List.jsx`, vamos adicionar uma classe quando o status do item for igual a `disabled`, dessa forma, podemos aplicar uma estilização para distinguir um item concluído de outro, então no componente `Box` vamos apenas adicionar uma linha:
```javascript
...
<Box
...
className={task.status === "disabled" ? "finished" : ""}
/>
...
```
Ficando assim:
![Lista com itens finalizados](https://dev-to-uploads.s3.amazonaws.com/i/nsafw3943103hhg9s3ou.png)
## Transformando o app em extensão 🌠 <a name="transformando-app"></a>
E finalizamos a nossa aplicação, agora vamos a parte que realmente importa, a parte da integração com o Google Chrome.
Segundo a [documentação](https://developer.chrome.com/docs/extensions/mv2/getstarted), precisamos preencher o manifesto de acordo com algumas [diretrizes do Google](https://developer.chrome.com/docs/extensions/mv2/getstarted/#manifest), então vamos editar nosso arquivo `manifest.json` que fica na pasta `public` e adicionar algumas entradas novas que são necessárias para que o Google Chrome reconheça nosso projeto como uma extensão ficando assim:
```json
{
  "name": "TODO - Tulio Calil",
  "description": "Aplicação de TODO com React",
  "version": "1.0",
  "manifest_version": 2,
  "browser_action": {
    "default_popup": "index.html",
    "default_title": "TODO App"
  }
}
```
As tags `name`, `description` e `version` são autoexplicativas, então vamos para `manifest_version`, que como o nome diz é a versão do manifesto, ela é necessária para que o Chrome entenda qual versão estamos requerindo para o nosso projeto, informamos a versão `2` por que a versão `1` é para Google Chrome anterior a versão 18. [Leia mais aqui sobre essa tag](https://developer.chrome.com/docs/apps/manifest/manifest_version/). 
Em `browser_action` temos duas opções, uma é a `default_popup` que informa qual arquivo padrão a ser carregado pela extensão e a outra `default_title` que é o titulo padrão.
Com tudo isso configurado, só nos resta mais um pequeno passo, que é desativar a opção de scripts em linha (inline scripts) quando gerarmos nossa build, pois por padrão o React gera builds dessa forma. Então vamos criar um arquivo na raiz do nosso projeto chamado: `.env.production` e nele vamos colocar o seguinte conteúdo:
```env
INLINE_RUNTIME_CHUNK=false
```
Agora podemos finalmente gerar uma build do nosso projeto e importa-lo como uma extensão, então no terminal vamos rodar:
```bash
yarn build
#ou
npm run build
```
E após concluir o processo de build, vamos no Google chrome: clique no ícone de três pontos `...` > `Mais ferramentas` > `Extensões`, iremos direto para a tela de extensões do Chrome. Vamos habilitar a opção de desenvolvedor e vamos clicar em "Carregar se compactação":
![Tela de extensões do Chrome](https://dev-to-uploads.s3.amazonaws.com/i/rvj67ydmq0axrnfvifab.jpg)
Agora, navegue até a pasta do projeto e abra a pasta build e selecione-a:
![Explorer selecionando pasta do build](https://dev-to-uploads.s3.amazonaws.com/i/ooxh5b429k4ian9go5yk.png)
Você verá que sua extensão foi adicionada com sucesso as extensões do Chrome:
![Extensão adicionada ao Chrome](https://dev-to-uploads.s3.amazonaws.com/i/xxziz55typ56lfwzeh1m.png)
Para abri-la basta clicar no botão de extensões (perto dos três pontos) e clicar (ou fixar) que ela irá abrir:
![Extensão rodando com tarefas adicionadas](https://dev-to-uploads.s3.amazonaws.com/i/p6p54941yo8kdbz7ef49.png)
## Conclusão 🎯 <a name="conclusao"></a>
Como podem ver, não temos muito segredo quando vamos criar uma extensão para o Google Chrome utilizando React, obviamente temos diversas apis do chrome para acessar como: Histórico, armazenamento, controle de abas e janelas e varias outras coisas. Abordei um exemplo mais simples para que esse tutorial sirva como uma introdução.
Espero que tenham gostado, até a próxima!

Aqui tem o projeto no Github caso queira usar para consultar ou mesmo fazer o clone e rodar:
{% github tuliocll/todo-google-chrome %}

Aqui tem a [doc](https://developer.chrome.com/docs/extensions/) das extensões com todos os recursos que você pode ter acesso.