2323 <li >
2424 <a
2525 href =" #about"
26- class =" font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
26+ :class =" isActive('about') ? 'text-blue-600 dark:text-blue-400' : 'text-gray-700 dark:text-gray-300'"
27+ class =" font-medium hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
2728 >About</a
2829 >
2930 </li >
3031 <li >
3132 <a
3233 href =" #publications"
33- class =" font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
34+ :class =" isActive('publications') ? 'text-blue-600 dark:text-blue-400' : 'text-gray-700 dark:text-gray-300'"
35+ class =" font-medium hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
3436 >Publications</a
3537 >
3638 </li >
3739 <li >
3840 <a
3941 href =" #evolution"
40- class =" font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
42+ :class =" isActive('evolution') ? 'text-blue-600 dark:text-blue-400' : 'text-gray-700 dark:text-gray-300'"
43+ class =" font-medium hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
4144 >Evolution</a
4245 >
4346 </li >
4447 <li >
4548 <a
4649 href =" #authors"
47- class =" font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
50+ :class =" isActive('authors') ? 'text-blue-600 dark:text-blue-400' : 'text-gray-700 dark:text-gray-300'"
51+ class =" font-medium hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
4852 >Authors</a
4953 >
5054 </li >
5155 <li >
5256 <a
5357 href =" #contributors"
54- class =" font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
58+ :class =" isActive('contributors') ? 'text-blue-600 dark:text-blue-400' : 'text-gray-700 dark:text-gray-300'"
59+ class =" font-medium hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
5560 >Contributors</a
5661 >
5762 </li >
146151 <a
147152 href =" #about"
148153 @click =" closeMobileMenu"
149- class =" block px-3 py-2 text-base font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
154+ :class =" isActive('about') ? 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-gray-800' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800'"
155+ class =" block px-3 py-2 text-base font-medium hover:text-blue-600 dark:hover:text-blue-400 rounded-md"
150156 >About</a
151157 >
152158 <a
153159 href =" #publications"
154160 @click =" closeMobileMenu"
155- class =" block px-3 py-2 text-base font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
161+ :class =" isActive('publications') ? 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-gray-800' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800'"
162+ class =" block px-3 py-2 text-base font-medium hover:text-blue-600 dark:hover:text-blue-400 rounded-md"
156163 >Publications</a
157164 >
158165 <a
159166 href =" #evolution"
160167 @click =" closeMobileMenu"
161- class =" block px-3 py-2 text-base font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
168+ :class =" isActive('evolution') ? 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-gray-800' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800'"
169+ class =" block px-3 py-2 text-base font-medium hover:text-blue-600 dark:hover:text-blue-400 rounded-md"
162170 >Evolution</a
163171 >
164172 <a
165173 href =" #authors"
166174 @click =" closeMobileMenu"
167- class =" block px-3 py-2 text-base font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
175+ :class =" isActive('authors') ? 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-gray-800' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800'"
176+ class =" block px-3 py-2 text-base font-medium hover:text-blue-600 dark:hover:text-blue-400 rounded-md"
168177 >Authors</a
169178 >
170179 <a
171180 href =" #contributors"
172181 @click =" closeMobileMenu"
173- class =" block px-3 py-2 text-base font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
182+ :class =" isActive('contributors') ? 'text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-gray-800' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800'"
183+ class =" block px-3 py-2 text-base font-medium hover:text-blue-600 dark:hover:text-blue-400 rounded-md"
174184 >Contributors</a
175185 >
176186 <button
@@ -233,13 +243,23 @@ export default {
233243 data () {
234244 return {
235245 isMobileMenuOpen: false ,
246+ activeSection: ' ' ,
247+ observer: null ,
236248 }
237249 },
238250 mounted () {
239251 // Init smooth scroll
240252 this .initSmoothScroll ()
253+ // Init scroll Spy
254+ this .initScrollSpy ()
255+ },
256+ beforeUnmount () {
257+ if (this .observer ) this .observer .disconnect ();
241258 },
242259 methods: {
260+ isActive (section ) {
261+ return this .activeSection === section;
262+ },
243263 toggleDarkMode () {
244264 this .$emit (" toggle-dark-mode" )
245265 },
@@ -249,14 +269,40 @@ export default {
249269 closeMobileMenu () {
250270 this .isMobileMenuOpen = false
251271 },
272+ initScrollSpy () {
273+ const sections = document .querySelectorAll (' section' );
274+
275+ const options = {
276+ root: null ,
277+ rootMargin: ' -45% 0px -45% 0px' ,
278+ threshold: 0
279+ };
280+
281+ this .observer = new IntersectionObserver ((entries ) => {
282+ entries .forEach ((entry ) => {
283+ if (entry .isIntersecting ) {
284+ this .activeSection = entry .target .id ;
285+ }
286+ });
287+ }, options);
288+
289+ sections .forEach ((section ) => {
290+ this .observer .observe (section);
291+ });
292+ },
252293 initSmoothScroll () {
294+ const self = this ;
295+
253296 document .querySelectorAll (' a[href^="#"]' ).forEach (anchor => {
254297 anchor .addEventListener (" click" , function (e ) {
255298 const href = this .getAttribute (" href" )
256299 if (href !== " #" && href .length > 1 ) {
257300 e .preventDefault ()
258301 const target = document .querySelector (href)
259302 if (target) {
303+ self .activeSection = href .substring (1 );
304+ self .closeMobileMenu ();
305+
260306 const headerOffset = 64
261307 const elementPosition = target .getBoundingClientRect ().top
262308 const offsetPosition =
0 commit comments