Loading indicators offer visual cues regarding ongoing processes.
They come in two main types: determinate and indeterminate.
In addition to these, Skeleton Screens and In-Component Loaders offer unique forms of feedback that do not fit neatly into the determinate or indeterminate categories:
In-component loaders offer localised feedback within specific UI elements, such as buttons or form fields, to inform users that an action is being processed.
Use in-component loaders sparingly; not all actions require them.
Reserve their use for tasks that take additional time or processing to ensure users stay informed without disrupting their workflow.
In Buttons:
In Fields:
/*Determinate Loading Indicators*/
/*Base*/
.progress-container {
display: flex;
flex-direction: column;
align-items: flex-start;
width: 100%;
}
.progress-label-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
progress {
height: 15px;
width: 100%;
appearance: none;
}
.determinate-linear-small {
height: 7px;
width: 100%;
appearance: none;
}
.progress-label {
font-size: 14px;
font-family: var(--base-font-family);
text-align: left;
}
.progress-count {
font-size: 14px;
font-family: var(--base-font-family);
font-weight: 600;
color: var(--MidBlue);
text-align: right;
margin-left: auto;
}
/* Style*/
progress::-webkit-progress-bar {
background-color: var(--Grey-xxl);
border-radius: 10px;
border: none;
}
progress::-webkit-progress-value {
background-color: var(--PuertoRico);
border-radius: 10px;
}
.determinate-linear::-webkit-progress-bar {
background-color: var(--Grey-xxl);
}
.determinate-linear::-webkit-progress-value {
background-color: var(--PuertoRico);
}
.determinate-linear-small::-webkit-progress-bar {
background-color: var(--Grey-xxl);
}
.determinate-linear-small::-webkit-progress-value {
background-color: var(--PuertoRico);
}
/*Doughnut*/
/* Pie */
#doughnut {
width: 100px;
height: 100px;
border-radius: 50%;
background: conic-gradient(var(--PuertoRico) 0deg 180deg,var(--Grey-xxl) 180deg 360deg);
position: relative;
}
/* Inner circle */
#inner_circle {
width: 75px;
height: 75px;
border-radius: 50%;
background: var(--White);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
align-items: center;
justify-content: center;
}
.progress-count-doughnut {
font-size: 18px;
font-family: var(--base-font-family);
font-weight: 500;
color: var(--Black);
text-align: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/*Indeterminate Loaders*/
.loader-container-il {
width: 150px;
height: 100px;
font-family: var(--base-font-family);
text-align: center;
color: black;
background-color: white;
border-radius: 10px;
border: none;
box-shadow: 0px 3px 6px rgba(0,0,0, 0.15);
margin: 10px;
padding: 20px 10px 20px 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
overflow: hidden;
}
/*In-component Loaders*/
/*Button loading States*/
.btn-primary.loading,
.btn-primary.loader-active {
background-color: var(--PuertoRico-xd);
border-color: var(--PuertoRico-xd);
color: white;
}
.btn-secondary.loading,
.btn-secondary.loader-active {
background-color: var(--PuertoRico-d);
border-color: var(--PuertoRico-d);
color: white;
}
.btn-tertiary.loading,
.btn-tertiary.loader-active {
background-color: var(--PuertoRico);
border-color: var(--PuertoRico);
color: white;
}
.btn-primary-small.loading,
.btn-primary-small.loader-active {
background-color: var(--PuertoRico-xd);
border-color: var(--PuertoRico-xd);
color: white;
}
.btn-secondary-small.loading,
.btn-secondary-small.loader-active {
background-color: var(--PuertoRico-d);
border-color: var(--PuertoRico-d);
color: white;
}
.btn-tertiary-small.loading,
.btn-tertiary-small.loader-active {
background-color: var(--PuertoRico);
border-color: var(--PuertoRico);
color: white;
}
/* Button loader */
.loader {
display: none;
border: 4px solid rgb(255, 255, 255, 0.5);
border-top: 4px solid white;
border-radius: 50%;
width: 14px;
height: 14px;
animation: spin 1s linear infinite;
padding: 0px;
margin-right: 7px;
}
/* Style for the loader to make it centered in the small buttons */
.btn-primary-small .loader {
position: absolute;
margin-right: 0px;
}
.btn-secondary-small .loader {
position: absolute;
margin-right: 0px;
}
.btn-tertiary-small .loader {
position: absolute;
margin-right: 0px;
}
/* Loader-active state (shared) */
button.loader-active {
cursor: wait;
}
/* Show loader on loading */
.loader-active .loader {
display: block;
}
/* Spinner animation */
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Hide icon when loader is visible */
#icon {
display: block;
}
/* Show the loader and hide the icon */
.loader-active #icon {
display: none;
}
.loader-active #loader {
display: block;
}
// Select the specific buttons by their IDs
const buttonIds = ["iconloader", "iconloader1", "iconloader2", "iconloader3", "iconloader4", "iconloader5", "iconloader6", "iconloader7", "iconloader8", "iconloader9"];
// Loop through each ID and apply loader behavior to the corresponding button
buttonIds.forEach((id) => {
const button = document.getElementById(id);
const loader = button.querySelector(".loader");
const icon = button.querySelector(".material-symbols-rounded");
button.addEventListener("click", function () {
// Add the loader-active class
button.classList.add("loader-active");
// Ensure the icon and loader visibility updates properly
if (icon) icon.style.display = "none";
if (loader) loader.style.display = "block";
// Simulate loading and revert after 3 seconds
setTimeout(function () {
button.classList.remove("loader-active");
if (icon) icon.style.display = "block";
if (loader) loader.style.display = "none";
}, 3000); // Adjust the duration as needed
});
});
// Select all buttons with class 'btn-base-small'
const buttons = document.querySelectorAll(".btn-base-small");
buttons.forEach(button => {
const loader = button.querySelector(".loader");
const icon = button.querySelector(".material-symbols-rounded");
button.addEventListener("click", function () {
// Add the loader-active class
button.classList.add("loader-active");
// Hide the icon and show the loader
if (icon) icon.style.display = "none";
if (loader) loader.style.display = "block";
// Simulate loading and revert after 3 seconds
setTimeout(function () {
button.classList.remove("loader-active");
if (icon) icon.style.display = "block";
if (loader) loader.style.display = "none";
}, 3000); // Adjust the duration as needed
});
});