1+ import { useEffect , useState } from "react"
12import Link from "next/link"
2- import colors from "../../styles/colors"
33import styles from "./SideMenu.module.css"
44import typographyStyles from "../../styles/typography.module.css"
5- import { useRouter } from "next/router "
5+ import colors from "../../styles/colors "
66import { Pages } from "../../types/types"
77
88function Menu ( { pages = [ ] } : { pages : Pages } ) {
9- const router = useRouter ( )
10- const { asPath : pathname } = router
9+ const [ activeSection , setActiveSection ] = useState < string > ( "" )
10+
11+ useEffect ( ( ) => {
12+ const handleScroll = ( ) => {
13+ const sections = pages . flatMap ( ( page ) =>
14+ [ page , ...( page . pages || [ ] ) ] . map ( ( p ) => ( {
15+ id : p . pathname . replace ( "#" , "" ) ,
16+ top :
17+ document . getElementById ( p . pathname . replace ( "#" , "" ) ) ?. offsetTop ||
18+ 0 ,
19+ } ) )
20+ )
21+
22+ const currentSection = sections . reduce ( ( acc , section ) => {
23+ const { id, top } = section
24+ if ( window . scrollY >= top - 100 ) {
25+ console . log ( id )
26+ return id
27+ }
28+ return acc
29+ } , "" )
30+
31+ setActiveSection ( currentSection )
32+ }
33+
34+ window . addEventListener ( "scroll" , handleScroll )
35+
36+ handleScroll ( )
37+
38+ return ( ) => window . removeEventListener ( "scroll" , handleScroll )
39+ } , [ pages ] )
40+
41+ const scrollToSection = ( sectionId : string , event : React . MouseEvent ) => {
42+ event . preventDefault ( )
43+ const element = document . getElementById ( sectionId . replace ( "#" , "" ) )
44+ if ( element ) {
45+ element . scrollIntoView ( { behavior : "smooth" } )
46+ }
47+ }
1148
1249 return (
1350 < aside className = { styles . menu } >
@@ -26,41 +63,57 @@ function Menu({ pages = [] }: { pages: Pages }) {
2663
2764 < ul className = "scrollArea" >
2865 { pages . map ( ( page ) => {
29- const isActive = pathname === page . pathname
66+ const isActive = activeSection === page . pathname . replace ( "#" , "" )
67+ const hasActiveChild = page . pages ?. some (
68+ ( subPage ) => activeSection === subPage . pathname . replace ( "#" , "" )
69+ )
3070
3171 return (
3272 < li
3373 key = { page . pathname }
34- className = { styles . menuItem }
74+ className = { `${ styles . menuItem } ${
75+ isActive || hasActiveChild ? styles . activeParent : ""
76+ } `}
3577 style = { {
3678 display : page ?. pages ? "block" : "flex" ,
3779 } }
3880 >
39- < code aria-hidden className = { styles . code } > { `</>` } </ code >
40- < Link
41- className = { isActive ? styles . isActive : "" }
81+ < code aria-hidden className = { styles . code } >
82+ { `</>` }
83+ </ code >
84+ < a
4285 href = { page . pathname }
86+ className = { isActive ? styles . isActive : "" }
87+ onClick = { ( e ) => scrollToSection ( page . pathname , e ) }
4388 >
4489 { page . name }
45- </ Link >
90+ </ a >
4691
4792 { page ?. pages && (
4893 < ul >
49- { page . pages . map ( ( page ) => {
50- const isActive = pathname === page . pathname
94+ { page . pages . map ( ( subPage ) => {
95+ const isSubActive =
96+ activeSection === subPage . pathname . replace ( "#" , "" )
5197
5298 return (
53- < li key = { page . pathname } className = { styles . menuItem } >
54- < code
55- aria-hidden
56- className = { styles . code }
57- > { `</>` } </ code > { " " }
58- < Link
59- className = { isActive ? styles . isActive : "" }
60- href = { page . pathname }
99+ < li
100+ key = { subPage . pathname }
101+ className = { `${ styles . menuItem } ${
102+ isSubActive ? styles . activeItem : ""
103+ } `}
104+ >
105+ < code aria-hidden className = { styles . code } >
106+ { `</>` }
107+ </ code >
108+ < a
109+ href = { subPage . pathname }
110+ className = { isSubActive ? styles . isActive : "" }
111+ onClick = { ( e ) =>
112+ scrollToSection ( subPage . pathname , e )
113+ }
61114 >
62- { page . name }
63- </ Link >
115+ { subPage . name }
116+ </ a >
64117 </ li >
65118 )
66119 } ) }
0 commit comments