feat(i18n): add multilingual support and interactive features
This commit is contained in:
+153
@@ -0,0 +1,153 @@
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
/* =========================
|
||||
MENU MOBILE
|
||||
========================= */
|
||||
|
||||
const menuButton = document.querySelector(".menu-toggle");
|
||||
const themeToggle = document.getElementById("theme-toggle");
|
||||
const navMenu = document.querySelector(".nav-links");
|
||||
|
||||
if (menuButton) {
|
||||
menuButton.addEventListener("click", () => {
|
||||
navMenu.classList.toggle("open");
|
||||
});
|
||||
}
|
||||
|
||||
/* =========================
|
||||
THEME
|
||||
========================= */
|
||||
|
||||
const savedTheme =
|
||||
localStorage.getItem(
|
||||
"portfolio-theme"
|
||||
) || "dark";
|
||||
|
||||
document.documentElement.setAttribute(
|
||||
"data-theme",
|
||||
savedTheme
|
||||
);
|
||||
|
||||
themeToggle.textContent =
|
||||
savedTheme === "light"
|
||||
? "☀️"
|
||||
: "🌙";
|
||||
|
||||
themeToggle.addEventListener(
|
||||
"click",
|
||||
() => {
|
||||
|
||||
const currentTheme =
|
||||
document.documentElement.getAttribute(
|
||||
"data-theme"
|
||||
);
|
||||
|
||||
const nextTheme =
|
||||
currentTheme === "dark"
|
||||
? "light"
|
||||
: "dark";
|
||||
|
||||
document.documentElement.setAttribute(
|
||||
"data-theme",
|
||||
nextTheme
|
||||
);
|
||||
|
||||
localStorage.setItem(
|
||||
"portfolio-theme",
|
||||
nextTheme
|
||||
);
|
||||
|
||||
themeToggle.textContent =
|
||||
nextTheme === "light"
|
||||
? "☀️"
|
||||
: "🌙";
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
/* =========================
|
||||
BOTÃO TOPO
|
||||
========================= */
|
||||
|
||||
const backToTop = document.getElementById("backToTop");
|
||||
|
||||
window.addEventListener("scroll", () => {
|
||||
|
||||
if (window.scrollY > 500) {
|
||||
backToTop.classList.add("show");
|
||||
} else {
|
||||
backToTop.classList.remove("show");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
backToTop.addEventListener("click", () => {
|
||||
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: "smooth"
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/* =========================
|
||||
ANIMAÇÃO DAS SEÇÕES
|
||||
========================= */
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
entries => {
|
||||
|
||||
entries.forEach(entry => {
|
||||
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add("show-element");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
{
|
||||
threshold: 0.15
|
||||
}
|
||||
);
|
||||
|
||||
document
|
||||
.querySelectorAll(
|
||||
".section, .metric-card, .card, .project-card"
|
||||
)
|
||||
.forEach(element => observer.observe(element));
|
||||
|
||||
/* =========================
|
||||
NAVBAR ATIVA
|
||||
========================= */
|
||||
|
||||
const sections = document.querySelectorAll("section");
|
||||
const navLinks = document.querySelectorAll(".nav-links a");
|
||||
|
||||
window.addEventListener("scroll", () => {
|
||||
|
||||
let current = "";
|
||||
|
||||
sections.forEach(section => {
|
||||
|
||||
const sectionTop = section.offsetTop - 140;
|
||||
|
||||
if (window.scrollY >= sectionTop) {
|
||||
current = section.getAttribute("id");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
navLinks.forEach(link => {
|
||||
|
||||
link.classList.remove("active");
|
||||
|
||||
if (link.getAttribute("href") === `#${current}`) {
|
||||
link.classList.add("active");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user