DEV Community

Cover image for ⚛️⏳Parte 2: Criando um Timer com Histórico em React
Dev Maiqui 🇧🇷
Dev Maiqui 🇧🇷

Posted on • Edited on

⚛️⏳Parte 2: Criando um Timer com Histórico em React

Seguindo com a segunda parte do projeto que construí na formação React da Rocketseat, um projeto de duas páginas/telas, onde uma tela contém o timer, e a outra tela contém o histórico dos ciclos realizados.

Nesta segunda parte do projeto vamos focar na criação das rotas, no layout e estilização das páginas.

Caso queira adquirir os cursos da Rocketseat com o meu cupom de desconto Acesse esse link

Links úteis:

Capítulos:

1 - Criando as rotas

Nesta primeira parte vamos focar na criação das rotas da aplicação.

Uma rota é um padrão de URL que corresponde a uma determinada página ou recurso.

Vamos supor que você tenha um blog com as seguintes URLs:

/ (página inicial)
/sobre (página sobre)
/contato (página de contato)

Você pode definir as seguintes rotas para essas URLs:

/ -> home() (função que renderiza a página inicial)
/sobre -> about() (função que renderiza a página sobre)
/contato -> contact() (função que renderiza a página de contato)

Quando um usuário acessar /sobre, o sistema de roteamento irá identificar a rota correspondente e executar a função about(), que irá gerar o HTML da página "Sobre" e enviá-lo ao navegador do usuário.

E, para criar as rotas, precisamos instalar a biblioteca que nos ajudará a fazer isso de uma forma mais fácil.

1.1 - React Router DOM

Vamos instalar a biblioteca de roteamento com o comando:

$ npm i react-router-dom
Enter fullscreen mode Exit fullscreen mode

commit: chore: ➕ add route lib $ npm i react-router-dom

1.2 - Criando as páginas

Para testarmos as rotas, precisamos possuir as páginas, ou seja, os componentes que serão renderizados em tela quando uma URL for acessada.

Vamos criar o arquivo src/pages/History.tsx com o conteúdo:

export function History() {
  return <h1>History</h1>;
}
Enter fullscreen mode Exit fullscreen mode

E também o arquivo src/pages/Home.tsx com o conteúdo:

export function Home() {
  return <h1>Home</h1>;
}
Enter fullscreen mode Exit fullscreen mode

1.3 - Removendo o componente Button

Vamos apagar os arquivos src/components/Button.tsx e src/components/Button.styles.ts, já que eles eram apenas para mostrar como o Styled Components funcionava.

E no arquivo src/App.tsx vamos remover o componente Button:

removendo o Button do arquivo  raw `src/App.tsx` endraw

1.4 - Criando o arquivo de rotas

Poderíamos colocar as rotas no arquivo src/App.tsx, mas para uma melhor organização, vamos criar o arquivo src/Router.tsx e colocar as rotas em um componente separado:

import { Route, Routes } from "react-router-dom";
import { History } from "./pages/History";
import { Home } from "./pages/Home";

export function Router() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/history" element={<History />} />
    </Routes>
  );
}
Enter fullscreen mode Exit fullscreen mode

E no arquivo src/App.tsx adicionamos o <BrowserRouter>:

import { ThemeProvider } from "styled-components";
import { BrowserRouter } from "react-router-dom";
import { Router } from "./Router";

import { GlobalStyle } from "./styles/global";
import { defaultTheme } from "./styles/themes/default";

export function App() {
  return (
    <ThemeProvider theme={defaultTheme}>
      <BrowserRouter>
        <Router />
      </BrowserRouter>
      <GlobalStyle />
    </ThemeProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Executando a nossa aplicação com npm run dev no endereço http://localhost:3000 podemos ver a página Home:

página home

E no endereço http://localhost:3000/history podemos ver a página History:

página history

commit: feat: ✨ add Router

1.5 - Context Providers

Você pôde perceber no arquivo src/App.tsx, que tanto o <ThemeProvider> quanto o , que não produzem nada visualmente na tela, são componentes que precisam ficar por fora dos nossos componentes que produzem algo visual na tela. E, tanto o <ThemeProvider> como o , são chamados de Context Providers.

Os Context Providers não produzem nenhum visual em tela, mas produzem um contexto para os componentes que estão dentro deles, ou seja, passam informações para esses componentes que estão dentro, no intuito desses componentes interiores saberem do contexto de fora.


2 - Layout de rotas

Nesta parte vamos entender o que é Layout de Rotas e como isso pode ajudar no desempenho da aplicação.

Olhando para as páginas, podemos observar que o Header se repete, independente da rota que acessarmos:

mostrando o header se repetindo nas duas páginas

Se em cada componente de página, nós adicionarmos o código do Header dentro, cada acesso do usuário em cada página, o Header estará sendo recriado, construído em tela do absoluto zero.

Podemos então deixar o código do Header em um único lugar para ser criado do zero apenas uma vez, melhorando assim o desempenho da aplicação.

2.1 - Criando o componente Header

Vamos criar o arquivo src/components/Header.tsx com o conteúdo:

export function Header() {
  return <h1>Header</h1>;
}
Enter fullscreen mode Exit fullscreen mode

E poderíamos ter em cada página o Header:

header na página Home

header na página History

Podemos ver que funciona:

rota Home funcionando com header, não performático

rota History funcionando com header, não performático

Mas se o Header vai estar em todas as páginas, tem jeito melhor de fazer, mais performático!

2.2 - Criando o DefaultLayout

Vamos criar o Layout Padrão que também será um componente, criando por primeiro o arquivo src/layouts/DefaultLayout.tsx com o conteúdo:

import { Outlet } from "react-router-dom";
import { Header } from "../components/Header";

export function DefaultLayout() {
  return (
    <div>
      <Header />
      <Outlet />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

O <Outlet /> é um espaço para inserir um conteúdo, um conteúdo que irá mudar dependendo da rota. Se a rota for / então o conteúdo de Outlet será do componente Home, se a rota for /history então o conteúdo de Outlet será do componente History. Ainda não irá funcionar, pois precisamos alterar as nossas rotas.

No arquivo src/Router.tsx:

import { Route, Routes } from "react-router-dom";
import { DefaultLayout } from "./layouts/DefaultLayout";
import { History } from "./pages/History";

import { Home } from "./pages/Home";

export function Router() {
  return (
    <Routes>
      <Route path="/" element={<DefaultLayout />}>
        <Route path="/" element={<Home />} />
        <Route path="/history" element={<History />} />
      </Route>

      {/* 
      - Um Exemplo de um layout diferente:

      - Para acessar a rota: "/admin/products"

      <Route path="/admin" element={<AdminLayout />}>
        <Route path="/" element={<Home />} />
        <Route path="/products" element={<History />} />
      </Route> 

      - Nesse caso todas as rotas que começarem com `path="/admin"` terão `<AdminLayout />` aplicado.
      */}
    </Routes>
  );
}
Enter fullscreen mode Exit fullscreen mode

O <Route path="/" element={<DefaultLayout />}> envolve as rotas Home e History, e o path="/" foi colocado, pois queremos aplicar o DefaultLayout para todas as rotas.

Se ao invés de path="/" fosse path="/teste", o DefaultLayout seria aplicado para todas as rotas que começassem com /teste.

commit: feat: ✨ add DefaultLayout


3 - Estilizando o Header

Nesta parte vamos estilizar o Header e a caixa por volta como na imagem abaixo:

Header estilizado

3.1 - Instalando o Phosphor Icons

Vamos utilizar uma família de ícones chamada Phosphor Icons e instalar a bilioteca phosphor-react

$ npm i phosphor-react
Enter fullscreen mode Exit fullscreen mode

Atualmente já existe uma biblioteca mais nova renomeada de @phosphor-icons/react.

commit: build: ➕ add icon lib $ npm i phosphor-react

3.2 - Criando pasta para cada componente

Vamos adotar apartir de agora uma organização para cada componente, já que vamos ter um arquivo de estilização no formato ts do Styled Components para cada componente.

Vamos fazer a refatoração do arquivo src/layouts/DefaultLayout.tsx, renomeando ele para src/layouts/DefaultLayout/index.tsx. Na mesma pasta vamos criar o arquivo de estilização src/layouts/DefaultLayout/styles.ts:

pasta DefaultLayout

Na mesma pasta do componente também podemos ter futuramente arquivos de teste e arquivos de tipagem, tudo relacionado ao componente por exemplo.

Vamos fazer outra refatoração parecida, agora com o Header:

src/components/Header.tsx -> src/components/Header/index.tsx

E vamos criar o arquivo src/components/Header/styles.ts

pasta do Header

3.3 - Estilizando o DefaultLayout

Vamos criar um componente estilizado chamado LayoutContainer no arquivo src/layouts/DefaultLayout/styles.ts:

import styled from "styled-components";

export const LayoutContainer = styled.div`
  max-width: 74rem;
  height: calc(100vh - 10rem);
  margin: 5rem auto;
  padding: 2.5rem;
  background: ${(props) => props.theme["gray-800"]};
  border-radius: 8px;
  display: flex;
  flex-direction: column;
`;
Enter fullscreen mode Exit fullscreen mode

E no arquivo src/layouts/DefaultLayout/index.tsx:

import { Outlet } from "react-router-dom";
import { Header } from "../../components/Header";
import { LayoutContainer } from "./styles";

export function DefaultLayout() {
  return (
    <LayoutContainer>
      <Header />
      <Outlet />
    </LayoutContainer>
  );
}
Enter fullscreen mode Exit fullscreen mode

Explicação do CSS:

1 - styled.div: A tag div foi escolhida pois se encaixa melhor nesse cenário, já que estamos criando a caixa onde ficará todo o conteúdo da página. A tag main NÃO foi escolhida nesse caso pois haverá o header e o footer dentro dessa tag, e a main seria mais apropriada para conter a funcionalidade principal da página.

2 - max-width: 74rem;: 70rem (1120px) é a largura da caixa, e somando mais o padding 2rem (32px) para cada lado, temos os 74rem de largura.

Podemos ver o tamanho da caixa no Figma conforme a imagem abaixo:

imagem do Figma mostrando o tamanho da caixa de 1120px

E conforme a gente dominui o tamanho no navegador, os 2rem de padding se mantém:

imagem do Projeto mostrando o tamanho do padding

Para essa margem de 2rem funcionar tive que adiconar margin: 2rem no arquivo src/styles/global.ts:

mostra o  raw `margin-inline: 2rem;` endraw  sendo adicionado no arquivo  raw `global.ts` endraw

margin-inline: 2rem; é a mesma coisa que margin: 0 2rem;.

OBS: Essa alteração não estatá junto do commit desta parte do artigo, pois apenas verifiquei isso no momento que eu estava escrevendo essa parte do artigo, já que não foi explicado nas aulas da Rocketseat.

3 - height: calc(100vh - 10rem);: 100vh é para que a caixa ocupe a altura inteira da página menos os 10rem da margem (5rem de margem no topo e 5rem de margem no bottom).

4 - margin: 5rem auto;: A margem possui 5rem (80px) de top e 5rem (80px) de bottom, como mostrado na imagem do Figma abaixo:

imagem do Figma mostrando o tamanho da margem da caixa de 80px de top e 80px de bottom

OBS: Para essas linhas laranjas com os valores das margens aparecerem no Figma, é preciso clicar na caixa e depois segurar a tecla option no Mac ou alt no Windows/Linux, e mover o mouse para a área desejada.

Já o valor auto para as laterais faz com que automaticamente seja calculado um valor de forma igual para cada margem lateral, assim o conteúdo acaba ficando centralizado.

3.4 - Código do Header/styles.ts

Vamos adicionar o CSS no arquivo src/components/Header/styles.ts:

import styled from "styled-components";

export const HeaderContainer = styled.header`
  display: flex;
  align-items: center;
  justify-content: space-between;
  nav {
    display: flex;
    gap: 0.5rem;
    a {
      width: 3rem;
      height: 3rem;
      display: flex;
      justify-content: center;
      align-items: center;
      color: ${(props) => props.theme["gray-100"]};
      border-top: 3px solid transparent;
      border-bottom: 3px solid transparent;
      &:hover {
        border-bottom: 3px solid ${(props) => props.theme["green-500"]};
      }
      &.active {
        color: ${(props) => props.theme["green-500"]};
      }
    }
  }
`;
Enter fullscreen mode Exit fullscreen mode

Caso você não esteja familizarizado com essa sintaxe &.active e &:hover recomendo olhar sobre CSS nesting. Essa sintaxe começou a aparecer no SASS e depois introduzido no CSS, por isso, favor verificar a compatibilidade dos navegadores no Can I use.

No arquivo src/components/Header/index.tsx:

import { HeaderContainer } from "./styles";
import { Scroll, Timer } from "phosphor-react";
import logoIgnite from "../../assets/logo-ignite.svg";
import { NavLink } from "react-router-dom";

export function Header() {
  return (
    <HeaderContainer>
      <span>
        <img src={logoIgnite} alt="" />
      </span>
      <nav>
        <NavLink to="/" title="Timer">
          <Timer size={24} />
        </NavLink>
        <NavLink to="/history" title="Histórico">
          <Scroll size={24} />
        </NavLink>
      </nav>
    </HeaderContainer>
  );
}
Enter fullscreen mode Exit fullscreen mode

O SVG do logo você pode pegar no Figma do projeto feito pela Rocketseat ou também está disponível no commit: feat: 💄 style Header and DefaultLayout


4 - Timer da Home Page

Nesta parte vamos começar a estilizar a página Home e, ao final, teremos esse resultado:

estilizando o timer da home

Após criar a pasta Home em src/pages/Home, coloque o arquivo src/pages/Home.tsx dentro desta pasta Home e renomeie o arquivo de Home.tsx para index.tsx:

src/pages/Home.tsx ➡️ src/pages/Home/index.tsx

Nesse novo arquivo src/pages/Home/index.tsx adicione o código abaixo:

import { Play } from "phosphor-react";
import {
  CountdownContainer,
  FormContainer,
  HomeContainer,
  Separator,
} from "./styles";

export function Home() {
  return (
    <HomeContainer>
      <form>
        <FormContainer>
          <label htmlFor="task">Vou trabalhar em</label>
          <input id="task" />
          <label htmlFor="minutesAmount">durante</label>
          <input type="number" id="minutesAmount" />
          <span>minutos.</span>
        </FormContainer>
        <CountdownContainer>
          <span>0</span>
          <span>0</span>
          <Separator>:</Separator>
          <span>0</span>
          <span>0</span>
        </CountdownContainer>
        <button type="submit">
          <Play size={24} />
          Começar
        </button>
      </form>
    </HomeContainer>
  );
}
Enter fullscreen mode Exit fullscreen mode

Nas aulas da Rocketseat não foi usada a unidade relativa rem para os ícones, mas eu acho bem interessante manter tudo com rem. Caso você queira usar o tamanho relativo do ícone em rem você pode usar desta forma abaixo como explicado na documentação:

{/* 24/16 = 1.5 */}

<Play size="1.5rem" />
Enter fullscreen mode Exit fullscreen mode

Vamos criar o arquivo de estilos src/pages/Home/styles.ts com o código:

export const HomeContainer = styled.main`
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  form {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3.5rem;
  }
`;

export const FormContainer = styled.div`
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  color: ${(props) => props.theme["gray-100"]};
  font-size: 1.125rem;
  font-weight: bold;
  flex-wrap: wrap;
`;

export const CountdownContainer = styled.div`
  font-family: "Roboto Mono", monospace;
  font-size: 10rem;
  line-height: 8rem;
  color: ${(props) => props.theme["gray-100"]};
  display: flex;
  gap: 1rem;
  span {
    background: ${(props) => props.theme["gray-700"]};
    padding: 2rem 1rem;
    border-radius: 8px;
  }
`;

export const Separator = styled.div`
  padding: 2rem 0;
  color: ${(props) => props.theme["green-500"]};
  width: 4rem;
  overflow: hidden;
  display: flex;
  justify-content: center;
`;
Enter fullscreen mode Exit fullscreen mode

Essa parte do Timer da Home Page a princípio não há nenhuma novidade, nada que a gente não tenha visto antes mas, caso você esteja com dúvida ainda com esse código, incentivo você a voltar para a Parte 1 onde é explicado detalhadamente sobre Styled Components.

Segue o commit desta parte: feat: 💄 style home countdown


5 - Finalizando a Home Page

Ao finalizar essa parte teremos a Home assim:

Home Page finalizada

Vamos criar mais componentes estilizados. Uma dica quando estamos utilizando Styled Components é evitar usar código em cascata e focar em criar componentes estilizados.

Por exemplo, poderíamos fazer o seguinte código para estilizarmos o botão, conforme mostra a imagem abaixo:

código css do botão dentro do componente HomeContainer

Mas isso não é indicado, dê preferência para criar um componente estilizado para esse botão, e é isso que vamos fazer nomeando esse componente de <StartCountdownButton>.

E o código final do aqruivo src/pages/Home/index.tsx será esse:

import { Play } from "phosphor-react";
import {
  CountdownContainer,
  FormContainer,
  HomeContainer,
  MinutesAmountInput,
  Separator,
  StartCountdownButton,
  TaskInput,
} from "./styles";

export function Home() {
  return (
    <HomeContainer>
      <form>
        <FormContainer>
          <label htmlFor="task">Vou trabalhar em</label>
          <TaskInput id="task" placeholder="Dê um nome para o seu projeto" />
          <label htmlFor="minutesAmount">durante</label>
          <MinutesAmountInput
            type="number"
            id="minutesAmount"
            placeholder="00"
          />
          <span>minutos.</span>
        </FormContainer>
        <CountdownContainer>
          <span>0</span>
          <span>0</span>
          <Separator>:</Separator>
          <span>0</span>
          <span>0</span>
        </CountdownContainer>
        <StartCountdownButton disabled type="submit">
          <Play size={24} />
          Começar
        </StartCountdownButton>
      </form>
    </HomeContainer>
  );
}
Enter fullscreen mode Exit fullscreen mode

E o código final do arquivo de estilização src/pages/Home/styles.ts:

import styled from "styled-components";

export const HomeContainer = styled.main`
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  form {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3.5rem;
  }
`;

export const FormContainer = styled.div`
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  color: ${(props) => props.theme["gray-100"]};
  font-size: 1.125rem;
  font-weight: bold;
  flex-wrap: wrap;
`;

const BaseInput = styled.input`
  background: transparent;
  height: 2.5rem;
  border: 0;
  border-bottom: 2px solid ${(props) => props.theme["gray-500"]};
  font-weight: bold;
  font-size: 1.125rem;
  padding: 0 0.5rem;
  color: ${(props) => props.theme["gray-100"]};
  &:focus {
    box-shadow: none;
    border-color: ${(props) => props.theme["green-500"]};
  }
  &::placeholder {
    color: ${(props) => props.theme["gray-500"]};
  }
`;

export const TaskInput = styled(BaseInput)`
  flex: 1;
`;

export const MinutesAmountInput = styled(BaseInput)`
  width: 4rem;
`;

export const CountdownContainer = styled.div`
  font-family: "Roboto Mono", monospace;
  font-size: 10rem;
  line-height: 8rem;
  color: ${(props) => props.theme["gray-100"]};
  display: flex;
  gap: 1rem;
  span {
    background: ${(props) => props.theme["gray-700"]};
    padding: 2rem 1rem;
    border-radius: 8px;
  }
`;

export const Separator = styled.div`
  padding: 2rem 0;
  color: ${(props) => props.theme["green-500"]};
  width: 4rem;
  overflow: hidden;
  display: flex;
  justify-content: center;
`;

export const StartCountdownButton = styled.button`
  width: 100%;
  border: 0;
  padding: 1rem;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-weight: bold;
  cursor: pointer;
  background: ${(props) => props.theme["green-500"]};
  color: ${(props) => props.theme["gray-100"]};
  &:disabled {
    opacity: 0.7;
    cursor: not-allowed;
  }
  &:not(:disabled):hover {
    background: ${(props) => props.theme["green-700"]};
  }
`;
Enter fullscreen mode Exit fullscreen mode

Nesse código temos algo novo que é o styled(BaseInput):

const BaseInput = styled.input`
  background: transparent;
  height: 2.5rem;
  border: 0;
  border-bottom: 2px solid ${(props) => props.theme["gray-500"]};
  font-weight: bold;
  font-size: 1.125rem;
  padding: 0 0.5rem;
  color: ${(props) => props.theme["gray-100"]};
  &:focus {
    box-shadow: none;
    border-color: ${(props) => props.theme["green-500"]};
  }
  &::placeholder {
    color: ${(props) => props.theme["gray-500"]};
  }
`;

export const TaskInput = styled(BaseInput)`
  flex: 1;
`;

export const MinutesAmountInput = styled(BaseInput)`
  width: 4rem;
`;
Enter fullscreen mode Exit fullscreen mode

Usando o styled(BaseInput) estamos criando um componente tendo como base o componente BaseInput, ou seja, estamos fazendo herança de estilização, assim evitamos repetir código.

commit dessa parte: feat: 💄 finish styling the home


6 - Aprimorando inputs

Vamos adicionar step={5} para quando clicado na seta ir aumentando de 5 em 5 minutos, um min={5} para aceitar no mínimo 5 minutos, e max={60} para aceitar no máximo 60 minutos, ou seja, uma hora.

input number

E também vamos adicionar o <datalist> que trará sugestões de projetos já feitos:

input com datalist

Altere o arquivo src/pages/Home/index.tsx:

git do arquivo  raw `src/pages/Home/index.tsx` endraw

Caso queira sumir com a seta do <datalist> no arquivo src/pages/Home/styles.ts:

git do  raw `src/pages/Home/styles.ts` endraw

Esse código para sumir com a seta é específico para o browser Google Chrome. Para cada browser há uma maneira específica de sumir com a seta.

commit: feat: ✨ add datalist


7 - Tabela da History Page

Nesta parte iremos construir e estilizar a tabela, no final o resultado será esse:

tabela da página history

Após criar a pasta History em src/pages/History, coloque o arquivo src/pages/History.tsx dentro desta pasta History e renomeie o arquivo de History.tsx para index.tsx:

src/pages/History.tsx ➡️ src/pages/History/index.tsx

Nesse novo arquivo src/pages/History/index.tsx adicione o código abaixo:

import { HistoryContainer, HistoryList } from "./styles";

export function History() {
  return (
    <HistoryContainer>
      <h1>Meu histórico</h1>
      <HistoryList>
        <table>
          <thead>
            <tr>
              <th>Tarefa</th>
              <th>Duração</th>
              <th>Duração</th>
              <th>Status</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Tarefa</td>
              <td>20 minutos</td>
              <td>Há 2 meses</td>
              <td>Concluído</td>
            </tr>
            <tr>
              <td>Tarefa</td>
              <td>20 minutos</td>
              <td>Há 2 meses</td>
              <td>Concluído</td>
            </tr>
            <tr>
              <td>Tarefa</td>
              <td>20 minutos</td>
              <td>Há 2 meses</td>
              <td>Concluído</td>
            </tr>
            <tr>
              <td>Tarefa</td>
              <td>20 minutos</td>
              <td>Há 2 meses</td>
              <td>Concluído</td>
            </tr>
            <tr>
              <td>Tarefa</td>
              <td>20 minutos</td>
              <td>Há 2 meses</td>
              <td>Concluído</td>
            </tr>
            <tr>
              <td>Tarefa</td>
              <td>20 minutos</td>
              <td>Há 2 meses</td>
              <td>Concluído</td>
            </tr>
            <tr>
              <td>Tarefa</td>
              <td>20 minutos</td>
              <td>Há 2 meses</td>
              <td>Concluído</td>
            </tr>
          </tbody>
        </table>
      </HistoryList>
    </HistoryContainer>
  );
}
Enter fullscreen mode Exit fullscreen mode

Nesta mesma pasta crie o arquivo de estilização src/pages/History/styles.ts com o código:

import styled from "styled-components";

export const HistoryContainer = styled.main`
  flex: 1;
  padding: 3.5rem;
  display: flex;
  flex-direction: column;
  h1 {
    font-size: 1.5rem;
    color: ${(props) => props.theme["gray-100"]};
  }
`;

export const HistoryList = styled.div`
  flex: 1;
  overflow: auto;
  margin-top: 2rem;
  table {
    width: 100%;
    border-collapse: collapse;
    min-width: 600px;
    th {
      background-color: ${(props) => props.theme["gray-600"]};
      padding: 1rem;
      text-align: left;
      color: ${(props) => props.theme["gray-100"]};
      font-size: 0.875rem;
      line-height: 1.6;
      &:first-child {
        border-top-left-radius: 8px;
        padding-left: 1.5rem;
      }
      &:last-child {
        border-top-right-radius: 8px;
        padding-right: 1.5rem;
      }
    }
    td {
      background-color: ${(props) => props.theme["gray-700"]};
      border-top: 4px solid ${(props) => props.theme["gray-800"]};
      padding: 1rem;
      font-size: 0.875rem;
      line-height: 1.6;
      &:first-child {
        width: 50%;
        padding-left: 1.5rem;
      }
      &:last-child {
        padding-right: 1.5rem;
      }
    }
  }
`;
Enter fullscreen mode Exit fullscreen mode

Porque esse <HistoryList> foi criado? No mobile há uma dificuldade em mostrar tabelas, e esse <HistoryList> foi criado para que quando a tela estiver no tamanho de mobile, o usuário consiga dar scroll para o lado. Não há como fazer scroll com table apenas com div.

O que faz esse border-collapse: collapse;? junta duas bordas da tabela em uma só borda. Se cada borda possui 1px quando as colunas se encontrarem ao invés da borda ter 2px, terá apenas uma borda de 1px. Resumindo mantém todas as linhas da tabela na mesma proporção.

commit: feat: ✨ add History page with styles


8 - Status da Tabela da History Page 🟡🔴🟢

Agora vamos para o código das cores do indicador da coluna de status:

coluna de status com as bolinhas coloridas

Pederíamos criar um componente React para <Status> mas nesse caso como será utilizado apenas na página History, vamos criar somente um Styled Component.

Nesse caso, não vou colocar o código aqui pois é mais interessante visualizar as alterações no GitHub, então por favor acesse o commit abaixo:

commit: feat: ✨ add status color to History page


9 - 🐛 statusColour ➡️ $statusColour

Agora vamos corrigir um bug, acessando o seu terminal do navegador provavelmente você verá um erro parecido com esse:

bug do status color

Alguns alunos da Rocketseat comentaram sobre esse bug no commit da aula

Para corrigir o problema eu segui a documentação do Styled Components

E a minha solução está nesse commit: 🐛 change statusColour to $statusColour

E assim finalizamos a parte 2 🎉

Image of Docusign

Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more