Crie um componente Progress Stepper (perfeito para formulários)

Um componente de passo de progresso é uma ferramenta adicionada aos formulários para agilizar a interação do usuário, dividindo as tarefas em etapas gerenciáveis. Ele oferece uma navegação direta, acompanha visualmente o progresso e aprimora a experiência do usuário.

Este tutorial cobrirá a construção de um componente de passo de progresso com HTML, CSS e JavaScript.

Estrutura HTML

A estrutura HTML será composta pelos seguintes elementos:

  • Quatro elementos div circulares para representar as 4 etapas do processo de navegação.
  • Duas barras horizontais.
  • Anterior e Próximo botões para navegar entre as etapas.
  • Um componente de mensagem para exibir quaisquer mensagens informativas.
1
     class="container">
2
       class="progress-container">
3
         class="progress-bar">
4
         class="status-bar">
5

6
         class="circle active">
7
           Step 1
8
           class="fa-solid fa-check">
9
        
10
         class="circle">
11
           Step 2
12
           class="fa-solid fa-check">
13
        
14
         class="circle">
15
           Step 3
16
           class="fa-solid fa-check">
17
        
18
         class="circle">
19
           Step 4
20
           class="fa-solid fa-check">
21
        
22
      
23
       class="buttons">
24
         class="prev-btn">Previous
25
         class="next-btn">Next
26
         class="submit">Submit
27
      
28
    
29

30
     class="message">
31
       class="fa-solid fa-check">
32
      

Your details have been submitted

33
    

Estilizando com CSS

Vamos começar aplicando os seguintes estilos ao corpo para garantir que o conteúdo fique centralizado.

1
body {
2
    min-height: 100vh;
3
    background-color: rgb(231, 233, 242);
4
    display: flex;
5
    justify-content: center;
6
    align-items: center;
7
    font-family: "Roboto", sans-serif;
8
  }

Então, teremos um contêiner para armazenar todos os nossos elementos:

1
.container {
2
    width: 700px;
3
    height: 300px;
4
  }

Teremos outro contêiner que usa Flexbox para garantir que os círculos que representam as diferentes etapas sejam espaçados uniformemente ao longo do eixo horizontal.

1
.progress-container {
2
    width: 100%;
3
    display: flex;
4
    justify-content: space-between;
5
    margin: 50px auto;
6
    position: relative;
7
  }

Vamos tornar os elementos div que representam as etapas circulares, fornecendo dimensões iguais e um raio de borda.

1
.circle  {
2
    width: 50px;
3
    height: 50px;
4
    background-color: white;
5
    border-radius: 50%;
6
    position: relative;
7
  }

Também precisamos garantir que os ícones estejam posicionados no centro dos círculos e que a extensão esteja diretamente abaixo do círculo correspondente. Por padrão, todos os ícones ficarão invisíveis.

1
  .circle span {
2
    position: absolute;
3
    top: 150%;
4
    left: 9%;
5
    color: #141d0d;
6
    
7
  }
8

9
  .circle i {
10
    position: absolute;
11
    top: 35%;
12
    left: 35%;
13
    display: none;
14
    
15
  }

Por padrão, o primeiro círculo terá o ícone visível e também terá um fundo verde.

1
.circle.active i {
2
    display: block;
3
  }
4

5
  .active {
6
    display: block;
7
    background-color: #43880f;
8
  }

Os botões terão os seguintes estilos.

1
.buttons {
2
  display: flex;
3
  justify-content: center;
4
  align-items: center;
5
  position: relative;
6
}
7
button {
8
  color: white;
9
  width: 100px;
10
  padding: 10px 20px;
11
  margin: 20px auto;
12
  border-radius: 3px;
13
  background-color: #43880f;
14
  border: none;
15
}
16
.next {
17
  color: white;
18
  /* background-color: rgb(87, 87, 202); */
19
}
20
.submit {
21
  display: none;
22
}
23
button:disabled {
24
  cursor: not-allowed;
25
  background-color: gray;
26
}

Por padrão, o botão enviar ficará oculto. Ele será exibido quando um usuário concluir todas as etapas necessárias.

As barras horizontais (barra de progresso e barra de status) serão posicionadas atrás dos círculos. A primeira barra (.progress-bar) ficará inativo, enquanto a segunda barra (.status-bar) a duração será animada dependendo do progresso do usuário.

1
.progress-bar {
2
width: 99%;
3
height: 5px;
4
background-color: grey;
5
position: absolute;
6
top: 50%;
7
left: 0;
8

9
z-index: -1;
10
}
11
.status-bar {
12
width: 100%;
13
height: 5px;
14
background-color: transparent;
15
position: absolute;
16
top: 50%;
17
left: 0;
18
z-index: -1;
19
}
20
.animate {
21
animation: fill 0.5s ease-in-out 0.4s forwards;
22
}
23

24
@keyframes fill {
25
100% {
26
  box-shadow: inset 0px 0px 0px 30px #43880f;
27
}
28
}

Finalmente, o componente de mensagem terá os seguintes estilos e ficará oculto por padrão:

1
.message {
2
    width: 500px;
3
    height: 300px;
4
    border-radius: 5px;
5
    border: 2px solid;
6
    gap: 10px;
7
    display: block;
8
    text-align: center;
9
    padding: 100px 5px;
10
    display: none;
11
  }
12

13
  .message i {
14
    margin-bottom: 50px;
15
    font-size: 25px;
16
    padding: 20px 20px;
17
    background-color: rgb(230, 111, 196);
18
    border-radius: 50%;
19
    animation: fillIcon 0.8s ease alternate;
20
  }
21
        @keyframes fillIcon {
22
    0% {
23
      transform: scale(1);
24
    }
25
    100% {
26
      transform: scale(1.2);
27
    }
28
  }

Funcionalidade JavaScript

É hora de fazer isso funcionar! A primeira coisa que precisamos fazer é obter os elementos:

1
const progressBar = document.querySelectorAll(".progress-bar")[0];
2
const StatusBar = document.querySelectorAll(".status-bar")[0];
3

4
const circles = document.querySelectorAll(".circle");
5
const previousBtn = document.querySelector(".prev-btn");
6
const nextBtn = document.querySelector(".next-btn");
7
const submitBtn = document.querySelector(".submit");
8
const message = document.querySelector(".message");

Crie uma variável currentStepIndex para acompanhar a etapa atualmente ativa em nosso componente de progresso.

1
let activeStepperIndex = 0;

Em seguida, adicione um ouvinte de evento de clique no Próximo botão. Quando o botão é clicado, o currentStepIndex aumentará em 1, movendo efetivamente o indicador de progresso para a próxima etapa.

1
nextBtn.addEventListener("click", function () {
2
  activeStepperIndex++;
3
  updateStepper();
4
});

O UpdateStepper() função exibirá o ícone de verificação dependendo do novo valor do currentStepIndex.

Defina uma função chamada updateStepper().

1
function updateStepper() {
2
      circles.forEach((circle, index) => {
3
        const textI = circle.querySelector("i");
4
        if (index === activeStepperIndex) {
5
          previousBtn.style.backgroundColor = "grey";
6
          textI.style.display = "block";
7
          circle.classList.add("animate");
8
        }
9
        if (activeStepperIndex === 3) {
10
          nextBtn.style.display = "none";
11
          submitBtn.style.display = "block";
12
        }
13
      });
14
      // previousBtn.disabled = activeStepperIndex === 0;

15
    }

Dentro da função, usaremos o built-in forEach() método para iterar através de cada círculo

  • Se o índice atual corresponder ao activeStepperIndexexibiremos o ícone de verificação no círculo correspondente e também animaremos o círculo.
  • Se o activeStepperIndex for o último, ocultaremos o botão Avançar e exibiremos o botão enviar.

Também queremos mostrar a representação visual da barra de status. Atualize o ouvinte de eventos para o Próximo botão, conforme mostrado abaixo.

1
nextBtn.addEventListener("click", function () {
2
      activeStepperIndex++;
3
      console.log(activeStepperIndex);
4
      const percentageWidth =
5
        (activeStepperIndex / (circles.length - 1)) * 100;
6
      StatusBar.style.width = percentageWidth + "%";
7
      StatusBar.style.backgroundColor = "green";
8
    
9

10
      updateStepper();
11
      previousBtn.disabled = true;
12
    });

O visual adiciona um verde backgroundColor para indicar o progresso feito através da barra. A largura é obtida dividindo-se activeStepperIndex pelo número total de etapas (circles.length - 1 para ajustar a indexação baseada em zero) e multiplicar por 100 para obter o valor em porcentagem.

Por exemplo, se o passo estiver no passo 2, a largura será de 33,3% e assim por diante.

Por fim, quando o botão enviar estiver marcado, exibiremos o componente de mensagem ao usuário informando que seus dados foram enviados com sucesso.

Vamos adicionar um evento ouvinte para o botão enviar.

1
const message = document.querySelector(".message");
2
const container = document.querySelector(".container");
3

4
submitBtn.addEventListener("click", function () {
5
  message.style.display = "block";
6
  container.style.display = "none";
7
});
8
});

Dentro da função, tornamos o componente de mensagem visível enquanto ocultamos o componente de passo.

Conclusão

Neste tutorial, aprendemos como construir um componente stepper sem nenhuma estrutura adicional. Felizmente, agora você pode criar componentes de passo ainda mais avançados.

Deixe uma resposta