@@ -10,19 +10,29 @@ import styles from "./styles.module.css";
1010
1111function DocsCategoryDropdown ( { dropdownCategory } ) {
1212 const [ isOpen , setIsOpen ] = useState ( false ) ;
13+ const [ isVisible , setIsVisible ] = useState ( false ) ;
1314 const [ dropdownStyles , setDropdownStyles ] = useState ( {
1415 top : "0px" ,
1516 left : "0px" ,
1617 } ) ;
1718 const dropdownMenuRef = useRef ( null ) ;
1819 const triggerRef = useRef ( null ) ; // Reference for the individual menu item trigger
20+ const hideTimeoutRef = useRef ( null ) ;
1921
2022 const handleMouseEnter = ( ) => {
23+ if ( hideTimeoutRef . current ) {
24+ clearTimeout ( hideTimeoutRef . current ) ;
25+ hideTimeoutRef . current = null ;
26+ }
2127 setIsOpen ( true ) ;
28+ setTimeout ( ( ) => setIsVisible ( true ) , 10 ) ;
2229 } ;
2330
2431 const handleMouseLeave = ( ) => {
25- setIsOpen ( false ) ;
32+ setIsVisible ( false ) ;
33+ hideTimeoutRef . current = setTimeout ( ( ) => {
34+ setIsOpen ( false ) ;
35+ } , 150 ) ;
2636 } ;
2737
2838 // Use useEffect to update the dropdown position when isOpen changes
@@ -42,17 +52,17 @@ function DocsCategoryDropdown({ dropdownCategory }) {
4252 } else {
4353 // Align to center
4454 left =
45- triggerRect . left + triggerRect . width / 2 - dropdownRect . width / 2 ;
55+ triggerRect . left + triggerRect . width / 2 - dropdownRect . width / 2 ;
4656 }
4757
4858 // Ensure the dropdown doesn't go off-screen
4959 left = Math . max (
50- 10 ,
51- Math . min ( left , viewportWidth - dropdownRect . width - 10 ) ,
60+ 10 ,
61+ Math . min ( left , viewportWidth - dropdownRect . width - 10 ) ,
5262 ) ;
5363
5464 setDropdownStyles ( {
55- top : `${ triggerRect . bottom } px` , // Align the dropdown below the menu item
65+ top : `${ triggerRect . bottom } px` , // Back to original positioning
5666 left : `${ left } px` , // Align the dropdown with the menu item
5767 } ) ;
5868 }
@@ -67,132 +77,130 @@ function DocsCategoryDropdown({ dropdownCategory }) {
6777
6878 // Guard against undefined sidebar
6979 const isSelected =
70- sidebar && sidebar . name && dropdownCategory
71- ? sidebar . name === dropdownCategory . customProps . sidebar
72- : false ;
80+ sidebar && sidebar . name && dropdownCategory
81+ ? sidebar . name === dropdownCategory . customProps . sidebar
82+ : false ;
7383
7484 return (
75- < div
76- className = { styles . docsNavDropdownContainer }
77- onMouseEnter = { handleMouseEnter }
78- onMouseLeave = { handleMouseLeave }
79- >
85+ < div
86+ className = { styles . docsNavDropdownContainer }
87+ onMouseEnter = { handleMouseEnter }
88+ onMouseLeave = { handleMouseLeave }
89+ >
8090 < span
81- className = { styles . docsNavDropdownToolbarLink }
82- ref = { triggerRef } // Attach the ref to the individual link that triggers the dropdown
91+ className = { styles . docsNavDropdownToolbarLink }
92+ ref = { triggerRef } // Attach the ref to the individual link that triggers the dropdown
8393 >
8494 < Link
85- className = { `${ styles . docsNavDropdownToolbarTopLevelLink } ${ isSelected ? styles . docsNavSelected : ""
95+ className = { `${ styles . docsNavDropdownToolbarTopLevelLink } ${ isSelected ? styles . docsNavSelected : ""
8696 } `}
87- href = { dropdownCategory . customProps . href }
97+ href = { dropdownCategory . customProps . href }
8898 >
8999 < Translate
90- id = { `sidebar.dropdownCategories.category.${ dropdownCategory . label } ` }
91- description = { `Translation for ${ dropdownCategory . label } ` }
100+ id = { `sidebar.dropdownCategories.category.${ dropdownCategory . label } ` }
101+ description = { `Translation for ${ dropdownCategory . label } ` }
92102 >
93103 { dropdownCategory . label }
94104 </ Translate >
95105 </ Link > { " " }
96106 < DropdownCaret />
97107 </ span >
98- { isOpen && (
99- < DropdownContent
100- dropdownCategory = { dropdownCategory }
101- handleMouseLeave = { handleMouseLeave }
102- dropdownStyles = { dropdownStyles } // Pass the dynamic styles to position the dropdown
103- dropdownMenuRef = { dropdownMenuRef } // Pass the ref to the dropdown content
104- />
105- ) }
106- </ div >
108+ { isOpen && (
109+ < DropdownContent
110+ dropdownCategory = { dropdownCategory }
111+ handleMouseLeave = { handleMouseLeave }
112+ dropdownStyles = { dropdownStyles } // Pass the dynamic styles to position the dropdown
113+ dropdownMenuRef = { dropdownMenuRef } // Pass the ref to the dropdown content
114+ isVisible = { isVisible }
115+ />
116+ ) }
117+ </ div >
107118 ) ;
108119}
109120
110121export const DocsCategoryDropdownLinkOnly = ( { title, link } ) => {
111122 return (
112- < div className = { styles . docsNavDropdownContainer } >
113- < Link href = { link } className = { styles . docsNavDropdownToolbarTopLevelLink } >
114- < span > { title } </ span >
115- </ Link >
116- </ div >
123+ < div className = { styles . docsNavDropdownContainer } >
124+ < Link href = { link } className = { styles . docsNavDropdownToolbarTopLevelLink } >
125+ < span > { title } </ span >
126+ </ Link >
127+ </ div >
117128 ) ;
118129} ;
119130
120131const DropdownContent = ( {
121- dropdownCategory,
122- handleMouseLeave,
123- dropdownStyles,
124- dropdownMenuRef,
125- } ) => {
132+ dropdownCategory,
133+ handleMouseLeave,
134+ dropdownStyles,
135+ dropdownMenuRef,
136+ isVisible,
137+ } ) => {
126138 const [ hovered , setHovered ] = useState ( null ) ;
127139
128140 return (
129- < div
130- ref = { dropdownMenuRef }
131- className = { styles . docsNavDropdownMenu }
132- style = { { position : "fixed" , ...dropdownStyles } }
133- >
134141 < div
135- key = { 99 }
136- className = { `${ styles . docsNavMenuItem } ${ hovered === 99 ? styles . docsNavHovered : "" } ` }
137- onMouseEnter = { ( ) => setHovered ( 99 ) }
138- onMouseLeave = { ( ) => setHovered ( null ) }
142+ ref = { dropdownMenuRef }
143+ className = { `${ styles . docsNavDropdownMenu } ${ isVisible ? styles . visible : '' } ` }
144+ style = { { position : "fixed" , ...dropdownStyles } }
139145 >
140146 < Link
141- to = { dropdownCategory . customProps . href }
142- className = { styles . docsNavMenuHeader }
143- onClick = { handleMouseLeave }
144- >
145- < Translate
146- id = { `sidebar.dropdownCategories.category.${ dropdownCategory . label } ` }
147- description = { `Translation for ${ dropdownCategory . label } ` }
148- >
149- { dropdownCategory . label }
150- </ Translate >
151- </ Link >
152- < div className = { styles . docsNavMenuDescription } >
153- < Translate
154- id = { `sidebar.dropdownCategories.category.description.${ dropdownCategory . label } ` }
155- description = { `Translation for ${ dropdownCategory . label } description` }
156- >
157- { dropdownCategory . description }
158- </ Translate >
159- </ div >
160- </ div >
161- < hr className = { styles . docsNavMenuDivider } />
162- < div className = { styles . docsNavMenuItems } >
163- { dropdownCategory . items . map ( ( item , index ) => (
164- < div
165- key = { index }
166- className = { `${ styles . docsNavMenuItem } ${ hovered === index ? styles . docsNavHovered : "" } ` }
167- onMouseEnter = { ( ) => setHovered ( index ) }
147+ key = { 99 }
148+ to = { dropdownCategory . customProps . href }
149+ className = { `${ styles . docsNavMenuItem } ${ hovered === 99 ? styles . docsNavHovered : "" } ` }
150+ onMouseEnter = { ( ) => setHovered ( 99 ) }
168151 onMouseLeave = { ( ) => setHovered ( null ) }
169- >
170- < Link
171- to = { item . href }
172- className = { styles . docsNavItemTitle }
173- onClick = { handleMouseLeave }
152+ onClick = { handleMouseLeave }
153+ style = { { textDecoration : 'none' , display : 'block' } }
154+ >
155+ < div className = { styles . docsNavMenuHeader } >
156+ < Translate
157+ id = { `sidebar.dropdownCategories.category.${ dropdownCategory . label } ` }
158+ description = { `Translation for ${ dropdownCategory . label } ` }
174159 >
175- < Translate
176- id = { `sidebar.dropdownCategories.category.${ dropdownCategory . label } .${ item . label } ` }
177- description = { `Translation for ${ dropdownCategory . label } .${ item . label } ` }
178- >
179- { item . label }
180- </ Translate >
181-
182- </ Link >
183- < div className = { styles . docsNavItemDescription } >
184- < Translate
185- id = { `sidebar.dropdownCategories.category.${ dropdownCategory . label } .${ item . label } .description` }
186- description = { `Translation for ${ dropdownCategory . label } .${ item . label } description` }
187- >
188- { item . description }
189- </ Translate >
190-
191- </ div >
160+ { dropdownCategory . label }
161+ </ Translate >
162+ </ div >
163+ < div className = { styles . docsNavMenuDescription } >
164+ < Translate
165+ id = { `sidebar.dropdownCategories.category.description.${ dropdownCategory . label } ` }
166+ description = { `Translation for ${ dropdownCategory . label } description` }
167+ >
168+ { dropdownCategory . description }
169+ </ Translate >
192170 </ div >
193- ) ) }
171+ </ Link >
172+ < hr className = { styles . docsNavMenuDivider } />
173+ < div className = { styles . docsNavMenuItems } >
174+ { dropdownCategory . items . map ( ( item , index ) => (
175+ < Link
176+ key = { index }
177+ to = { item . href }
178+ className = { `${ styles . docsNavMenuItem } ${ hovered === index ? styles . docsNavHovered : "" } ` }
179+ onMouseEnter = { ( ) => setHovered ( index ) }
180+ onMouseLeave = { ( ) => setHovered ( null ) }
181+ onClick = { handleMouseLeave }
182+ style = { { textDecoration : 'none' , display : 'block' } }
183+ >
184+ < div className = { styles . docsNavItemTitle } >
185+ < Translate
186+ id = { `sidebar.dropdownCategories.category.${ dropdownCategory . label } .${ item . label } ` }
187+ description = { `Translation for ${ dropdownCategory . label } .${ item . label } ` }
188+ >
189+ { item . label }
190+ </ Translate >
191+ </ div >
192+ < div className = { styles . docsNavItemDescription } >
193+ < Translate
194+ id = { `sidebar.dropdownCategories.category.${ dropdownCategory . label } .${ item . label } .description` }
195+ description = { `Translation for ${ dropdownCategory . label } .${ item . label } description` }
196+ >
197+ { item . description }
198+ </ Translate >
199+ </ div >
200+ </ Link >
201+ ) ) }
202+ </ div >
194203 </ div >
195- </ div >
196204 ) ;
197205} ;
198206
@@ -211,24 +219,24 @@ const DropdownCaret = () => {
211219 } ;
212220
213221 return (
214- < span style = { { marginLeft : "8px" } } >
222+ < span style = { { marginLeft : "8px" } } >
215223 < svg
216- xmlns = "http://www.w3.org/2000/svg"
217- width = "6"
218- height = "10"
219- viewBox = "0 0 6 10"
220- style = { rotatedIconStyle }
224+ xmlns = "http://www.w3.org/2000/svg"
225+ width = "6"
226+ height = "10"
227+ viewBox = "0 0 6 10"
228+ style = { rotatedIconStyle }
221229 >
222230 < path
223- stroke = "currentColor"
224- strokeLinecap = "round"
225- strokeLinejoin = "round"
226- strokeWidth = "1.5"
227- d = "M1 9L5 5 1 1"
231+ stroke = "currentColor"
232+ strokeLinecap = "round"
233+ strokeLinejoin = "round"
234+ strokeWidth = "1.5"
235+ d = "M1 9L5 5 1 1"
228236 />
229237 </ svg >
230238 </ span >
231239 ) ;
232240} ;
233241
234- export default DocsCategoryDropdown ;
242+ export default DocsCategoryDropdown ;
0 commit comments