Coded with HTML
, SCSS
, JavaScript
This is a solution to the Advice generator app challenge on Frontend Mentor.
The challenge is to build out this advice generator app using the Advice Slip API and get it looking as close to the design as possible.
See Task.md for more details about the task.
Users should be able to:
Path | Description |
---|---|
public | Folder with .html and .css files |
public / index.html | Main HTML file |
public / index.css | Main CSS file, generated with SCSS transpiler |
src | Source files needed for application development |
src / assets | Images and other media used on the webpage |
src / index.scss | Main SCSS file, used to later generate CSS |
src / index.js | Main file with JS |
src / scripts | Folder with JS functions imported by index.js |
docs | Folder with additional information, documentation |
docs / images | Folder with the application screenshots |
docs / images / goals | Folder with images from Frontendmentor that show how the page should look like |
docs / images / results | Folder with screenshots of how the application works after being fully developed |
docs / README-template.md | Template for README.md, don't use it (from FrontendMentor) |
docs / style-guide.md | Style information: color palette, fonts, etc. (from FrontendMentor) |
docs / task.md | Detailed task description (from FrontendMentor) |
docs / advice-generator-app-main.zip | Initial archive provided by Frontend Mentor |
try {
const result = await fetch(API_URL, {
method: "GET",
});
const resultJSON = await result.json();
// ...
} catch (err) {
// ...
}
There is a limitation described in the docs of API: it can generate new quotes only once in 2 seconds. Thus I disabled the button after the pressing, then enable it in 3 seconds. During these 2 seconds I show spinning animation
&__button[disabled] &__icon-dice {
animation: rotate-360 3s infinite alternate ease-in-out;
}
&__button[disabled] {
animation: shade-fade 3s forwards infinite alternate ease-in-out;
}
@keyframes rotate-360 {
100% {
transform: rotate(360deg);
}
}
@keyframes shade-fade {
0% {
box-shadow: 0 0 32px 4px var(--primary-1);
}
100% {
box-shadow: 0 0 0px 0px var(--primary-1);
}
}
I achieved by toggling classes and adding a little setTimeout
setTimeout(() => {
removeClassFromElement(adviceText, "card__advice--out");
removeClassFromElement(adviceId, "card__id--out");
displayData(adviceId, resultJSON?.slip?.id ?? "-");
displayData(
adviceText,
resultJSON?.slip?.advice ?? "Unable to get the quote."
);
addClassToElement(adviceText, "card__advice--in");
addClassToElement(adviceId, "card__id--in");
}, 600); // 600ms helps to make all animations smooth - result of experiments
&__id--out {
animation: shrink-out 0.8s forwards;
}
&__id--in {
animation: shrink-in 0.8s forwards;
}
&__advice--out {
animation: fade-out 0.8s forwards;
}
&__advice--in {
animation: fade-in 0.8s forwards;
}
@keyframes fade-out {
0% {
transform: scale(1);
}
100% {
transform: scale(0);
}
}
@keyframes fade-in {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
@keyframes shrink-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes shrink-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
If user goes offline, notification shows up and disappears when he is back online. Notifications fade in and fade out with animation.
When I add a notification to the page, it starts with 0 opacity, then by the end of animation the opacity is 1.
When I remove the notification from the page, launch the animation that slowly turns the opacity to 0, after some delay I delete the element from the page.
addEventListener("offline", (event) => {
disableElement(generateQuoteButton);
const errorElement = displayError("You are offline");
const checkOnline = setInterval(() => {
const isOnline = window.navigator.onLine;
if (isOnline) {
enableElement(generateQuoteButton);
clearInterval(checkOnline);
errorElement.style.animation = "shrink-out 0.8s forwards";
setTimeout(() => {
removeElementFromPage(errorElement);
}, 800);
}
}, 1000);
});
try {
...
} catch (err) {
const errorElement = displayError(
"Something went wrong with receiving a quote"
);
setTimeout(() => {
errorElement.style.animation = "shrink-out 0.8s forwards";
setTimeout(() => {
removeElementFromPage(errorElement);
}, 800);
}, 3000);
}
@keyframes shrink-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes shrink-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
Nothing special, thanks to https://tobiasahlin.com/blog/css-trick-animating-link-underlines/
&--link::before {
content: "";
position: absolute;
display: block;
width: 100%;
height: 2px;
border-radius: 2px;
bottom: -2px;
left: 0;
background-color: var(--primary-2);
transform: scaleX(0);
transition: transform 0.5s ease;
}
&--link:hover::before {
transform: scaleX(1);
}
&--description {
font-size: 14px;
}
const generateQuoteButton = document.querySelector(".card__button");
/// ....
document.addEventListener("keydown", (e) => {
switch (e.key) {
case "Enter":
generateQuoteButton.focus();
generateQuoteButton.dispatchEvent("click");
return;
}
});
I use a free version of FrontendMentor. Thus I don’t have access to Figma prototypes. But that’s not a problem - I made my own one
Here it is: https://www.figma.com/file/gtbZrKQzY4Ovlz9kQWeBPR/Advice-Generator-App?node-id=0%3A1
That helped me to make the application as close to the photos as possible