<div class="container">
<div class="tab-status">
<span class="tab active">1</span>
<span class="tab">2</span>
<span class="tab">3</span>
</div>
<form action="#">
<div role="tab-list">
<div role="tabpanel" id="color" class="tabpanel">
<h3>What is your favorite color?</h3>
<textarea name="color" class="form-input" placeholder="Ruby red"></textarea>
</div>
<div role="tabpanel" id="hobbies" class="tabpanel hidden">
<h3>What are your hobbies?</h3>
<textarea name="hobbies" class="form-input" placeholder="Mountain climbing, Guitar, Skateboarding"></textarea>
</div>
<div role="tabpanel" id="occupation" class="tabpanel hidden">
<h3>What is your occupation?</h3>
<textarea name="occupation" class="form-input" placeholder="Web Designer"></textarea>
</div>
</div>
<div class="pagination">
<a class="btn hidden" id="prev">Previous</a>
<a class="btn" id="next">Continue</a>
<button class="btn btn-submit hidden" id="submit">Submit</button>
</div>
</form>
</div>
:root {
--color-1: #6366f1;
--color-1-hover: #4338ca;
--color-2: #06b6d4;
--color-2-hover: #0891b2;
--text-color: #312e81;
--status-btn-bg: #f8fafc;
--status-btn-bg-hover: #f1f5f9;
}
body {
background: linear-gradient(to left, var(--color-1), var(--color-2));
}
.container {
margin: 3rem auto;
max-width: 500px;
background: white;
border-radius: 1rem;
padding: 2rem;
}
.form-input {
width: 100%;
border: 1px solid #ddd;
border-radius: .5rem;
box-shadow: inset 0px 1px 2px rgba(0, 0, 0, .1);
padding: 1rem;
box-sizing: border-box;
color: var(--text-color);
transition: ease-in-out .3s all;
}
.form-input::placeholder {
color: #cbd5e1;
}
.form-input:focus {
outline: none;
border-color: var(--color-1);
}
.btn:focus-within,
.form-input:focus-within {
box-shadow: #f8fafc 0px 0px 0px 2px, #c7d2fe 0px 0px 0px 6px, #0000 0px 1px 2px 0px;
}
textarea.form-input {
min-height: 150px;
}
.btn {
border: 0;
background: var(--color-1);
padding: 1rem;
border-radius: 25px;
color: white;
cursor: pointer;
}
.btn[disabled] {
opacity: .5;
pointer-events: none;
}
.btn:hover {
background: var(--color-1-hover);
transition: ease-in-out .3s all;
}
.btn-submit {
background-color: var(--color-2);
}
.btn-submit:hover {
background-color: var(--color-2-hover);
}
.pagination {
margin-top: 1rem;
display: flex;
align-items: center;
justify-content: center;
}
.pagination .btn {
width: 100%;
text-align: center;
margin: 0 6px;
}
.tab-status {
display: flex;
align-items: center;
}
.tab-status span {
appearance: none;
background: var(--status-btn-bg);
border: none;
border-radius: 50%;
width: 2rem;
height: 2rem;
margin-right: .5rem;
display: flex;
align-items: center;
justify-content: center;
}
.tab-status span.active {
background-color: var(--color-2);
color: white;
}
.hidden {
display: none;
}
const previousButton = document.querySelector('#prev')
const nextButton = document.querySelector('#next')
const submitButton = document.querySelector('#submit')
const tabTargets = document.querySelectorAll('.tab')
const tabPanels = document.querySelectorAll('.tabpanel')
const isEmpty = (str) => !str.trim().length
let currentStep = 0
// Validate first input on load
validateEntry()
// Next: Change UI relative to current step and account for button permissions
nextButton.addEventListener('click', (event) => {
event.preventDefault()
// Hide current tab
tabPanels[currentStep].classList.add('hidden')
tabTargets[currentStep].classList.remove('active')
// Show next tab
tabPanels[currentStep + 1].classList.remove('hidden')
tabTargets[currentStep + 1].classList.add('active')
currentStep += 1
validateEntry()
updateStatusDisplay()
})
// Previous: Change UI relative to current step and account for button permissions
previousButton.addEventListener('click', (event) => {
event.preventDefault()
// Hide current tab
tabPanels[currentStep].classList.add('hidden')
tabTargets[currentStep].classList.remove('active')
// Show previous tab
tabPanels[currentStep - 1].classList.remove('hidden')
tabTargets[currentStep - 1].classList.add('active')
currentStep -= 1
nextButton.removeAttribute('disabled')
updateStatusDisplay()
})
function updateStatusDisplay() {
// If on the last step, hide the next button and show submit
if (currentStep === tabTargets.length - 1) {
nextButton.classList.add('hidden')
previousButton.classList.remove('hidden')
submitButton.classList.remove('hidden')
validateEntry()
// If it's the first step hide the previous button
} else if (currentStep == 0) {
nextButton.classList.remove('hidden')
previousButton.classList.add('hidden')
submitButton.classList.add('hidden')
// In all other instances display both buttons
} else {
nextButton.classList.remove('hidden')
previousButton.classList.remove('hidden')
submitButton.classList.add('hidden')
}
}
function validateEntry() {
let input = tabPanels[currentStep].querySelector('.form-input')
// Start but disabling continue button
nextButton.setAttribute('disabled', true)
submitButton.setAttribute('disabled', true)
// Validate on initial function fire
setButtonPermissions(input)
// Validate on input
input.addEventListener('input', () => setButtonPermissions(input))
// Validate if bluring from input
input.addEventListener('blur', () => setButtonPermissions(input))
}
function setButtonPermissions(input) {
if (isEmpty(input.value)) {
nextButton.setAttribute('disabled', true)
submitButton.setAttribute('disabled', true)
} else {
nextButton.removeAttribute('disabled')
submitButton.removeAttribute('disabled')
}
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.