feat(ui): redesign personal page with semantic structure, interactive navigation, and refined visual style

This commit is contained in:
2026-04-23 23:20:07 -03:00
parent 088b8a3b51
commit aa268f2380
3 changed files with 538 additions and 59 deletions

73
script.js Normal file
View File

@@ -0,0 +1,73 @@
const menuButton = document.querySelector('.menu-toggle');
const navLinks = document.querySelector('.nav-links');
if (menuButton && navLinks) {
menuButton.addEventListener('click', () => {
const isOpen = navLinks.dataset.open === 'true';
navLinks.dataset.open = String(!isOpen);
menuButton.setAttribute('aria-expanded', String(!isOpen));
});
navLinks.querySelectorAll('a').forEach((link) => {
link.addEventListener('click', () => {
navLinks.dataset.open = 'false';
menuButton.setAttribute('aria-expanded', 'false');
});
const highlightTarget = () => {
const targetId = link.getAttribute('href');
if (!targetId || !targetId.startsWith('#')) {
return;
}
const targetCard = document.querySelector(targetId);
if (targetCard) {
targetCard.classList.add('is-linked-hover');
link.classList.add('is-linked');
}
};
const clearTarget = () => {
const targetId = link.getAttribute('href');
if (!targetId || !targetId.startsWith('#')) {
return;
}
const targetCard = document.querySelector(targetId);
if (targetCard) {
targetCard.classList.remove('is-linked-hover');
link.classList.remove('is-linked');
}
};
link.addEventListener('mouseenter', highlightTarget);
link.addEventListener('mouseleave', clearTarget);
link.addEventListener('focus', highlightTarget);
link.addEventListener('blur', clearTarget);
});
}
const revealElements = document.querySelectorAll('.reveal');
if ('IntersectionObserver' in window && revealElements.length > 0) {
const observer = new IntersectionObserver(
(entries, currentObserver) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
currentObserver.unobserve(entry.target);
}
});
},
{ threshold: 0.2 }
);
revealElements.forEach((element) => observer.observe(element));
} else {
revealElements.forEach((element) => element.classList.add('is-visible'));
}
const yearElement = document.getElementById('currentYear');
if (yearElement) {
yearElement.textContent = new Date().getFullYear();
}