@@ -149,16 +149,23 @@ const { menu = [] } = Astro.props;
149149 currentSectionId = sections[0].id;
150150 }
151151
152- // Actualizamos clases
152+ // Actualizamos clases y URL
153153 navLinks.forEach((link) => {
154154 const href = link.getAttribute("href");
155155 if (!href) return;
156156
157- const linkId = href.substring(1); // Quitar el '#'
157+ // Extraer ID desde la URL limpia: "/" -> "home", "/skills" -> "skills"
158+ const linkId = href === "/" ? "home" : href.substring(1);
158159
159160 if (linkId === currentSectionId) {
160161 link.classList.add(...activeClasses);
161- link.setAttribute("aria-current", "page"); // Accesibilidad
162+ link.setAttribute("aria-current", "page");
163+
164+ // Actualizar URL del navegador solo si es diferente (sin recargar)
165+ const currentPath = window.location.pathname;
166+ if (currentPath !== href) {
167+ window.history.replaceState({ section: linkId }, "", href);
168+ }
162169 } else {
163170 link.classList.remove(...activeClasses);
164171 link.removeAttribute("aria-current");
@@ -190,31 +197,39 @@ const { menu = [] } = Astro.props;
190197 };
191198
192199 /**
193- * Configura el Smooth Scroll para enlaces internos
200+ * Configura el Smooth Scroll para enlaces internos con URLs limpias (sin #)
201+ * Usa History API para mantener URLs profesionales
194202 */
195203 const initSmoothScroll = (): void => {
204+ // Seleccionar enlaces internos (que empiezan con / y son de la misma página)
196205 document
197- .querySelectorAll<HTMLAnchorElement>('a[href^="#"] ')
206+ .querySelectorAll<HTMLAnchorElement>('nav a.nav-link ')
198207 .forEach((anchor) => {
199208 anchor.addEventListener("click", function (e) {
200209 e.preventDefault();
201210 const href = this.getAttribute("href");
202211 if (!href) return;
203212
204- const targetId = href.substring(1);
213+ // Extraer el ID de la sección desde la URL
214+ // "/" -> "home", "/skills" -> "skills"
215+ const targetId = href === "/" ? "home" : href.substring(1);
205216 const targetElement = document.getElementById(targetId);
206217
207218 if (targetElement) {
208- const headerOffset = 80; // Ajustar según la altura real de tu navbar
219+ const headerOffset = 80;
209220 const elementPosition = targetElement.getBoundingClientRect().top;
210221 const offsetPosition =
211222 elementPosition + window.scrollY - headerOffset;
212223
224+ // Scroll suave a la sección
213225 window.scrollTo({
214226 top: offsetPosition,
215227 behavior: "smooth",
216228 });
217229
230+ // Actualizar URL usando History API
231+ window.history.pushState({ section: targetId }, "", href);
232+
218233 // Cerrar menú móvil si está abierto
219234 const collapseTarget = document.getElementById("navbar-sticky");
220235 if (
@@ -229,6 +244,59 @@ const { menu = [] } = Astro.props;
229244 });
230245 };
231246
247+ /**
248+ * Maneja la navegación con botones atrás/adelante del navegador
249+ */
250+ const handleBrowserNavigation = (): void => {
251+ window.addEventListener("popstate", (event) => {
252+ if (event.state && event.state.section) {
253+ const targetElement = document.getElementById(event.state.section);
254+ if (targetElement) {
255+ const headerOffset = 80;
256+ const elementPosition = targetElement.getBoundingClientRect().top;
257+ const offsetPosition =
258+ elementPosition + window.scrollY - headerOffset;
259+
260+ window.scrollTo({
261+ top: offsetPosition,
262+ behavior: "smooth",
263+ });
264+ }
265+ } else {
266+ // Si no hay state, ir al inicio
267+ window.scrollTo({ top: 0, behavior: "smooth" });
268+ }
269+ });
270+ };
271+
272+ /**
273+ * Maneja la navegación inicial cuando se carga la página con una ruta específica
274+ * Ejemplo: si cargas /skills directamente, hace scroll a esa sección
275+ */
276+ const handleInitialNavigation = (): void => {
277+ const currentPath = window.location.pathname;
278+
279+ // Si no es la raíz, intentar scroll a la sección correspondiente
280+ if (currentPath !== '/') {
281+ const sectionId = currentPath.substring(1); // /skills -> skills
282+ const targetElement = document.getElementById(sectionId);
283+
284+ if (targetElement) {
285+ // Pequeño delay para asegurar que el DOM está listo
286+ setTimeout(() => {
287+ const headerOffset = 80;
288+ const elementPosition = targetElement.getBoundingClientRect().top;
289+ const offsetPosition = elementPosition + window.scrollY - headerOffset;
290+
291+ window.scrollTo({
292+ top: offsetPosition,
293+ behavior: 'smooth',
294+ });
295+ }, 100);
296+ }
297+ }
298+ };
299+
232300 // --- INICIALIZACIÓN MAESTRA ---
233301
234302 const initNavbar = (): void => {
@@ -237,6 +305,8 @@ const { menu = [] } = Astro.props;
237305 handleScrollSpy();
238306 initMobileMenu();
239307 initSmoothScroll();
308+ handleBrowserNavigation();
309+ handleInitialNavigation();
240310
241311 // 2. Event Listener para Scroll (Optimizado con requestAnimationFrame)
242312 let ticking = false;
0 commit comments