@@ -76,13 +76,6 @@ function showTopBar() {
7676 topbar . classList . add ( "show-top-menu" ) ;
7777 }
7878
79- // update sidebar
80- var sidebar = document . getElementsByClassName ( "docs-sidebar" ) ;
81- if ( sidebar . length > 0 ) {
82- sidebar [ 0 ] . classList . remove ( "hide-top-menu" ) ;
83- sidebar [ 0 ] . classList . add ( "show-top-menu" ) ;
84- }
85-
8679}
8780
8881// Function to hide the top bar menu
@@ -95,13 +88,6 @@ function hideTopBar() {
9588 topbar . classList . add ( "hide-top-menu" ) ;
9689 }
9790
98- // update sidebar
99- var sidebar = document . getElementsByClassName ( "docs-sidebar" ) ;
100- if ( sidebar . length > 0 ) {
101- sidebar [ 0 ] . classList . remove ( "show-top-menu" ) ;
102- sidebar [ 0 ] . classList . add ( "hide-top-menu" ) ;
103- }
104-
10591}
10692
10793// ajoute un event listener sur les touches du clavier
@@ -198,10 +184,12 @@ if (
198184 setTimeout ( topbarInjector , 1 ) ;
199185 setTimeout ( addEventListenerToShowHideTopbar , 1 ) ;
200186 setTimeout ( addSidebarToggleButton , 1 ) ;
187+ setTimeout ( addScrollTopBehavior , 1 ) ;
201188} else {
202189 document . addEventListener ( "DOMContentLoaded" , topbarInjector ) ;
203190 document . addEventListener ( "DOMContentLoaded" , addEventListenerToShowHideTopbar ) ;
204191 document . addEventListener ( "DOMContentLoaded" , addSidebarToggleButton ) ;
192+ document . addEventListener ( "DOMContentLoaded" , addScrollTopBehavior ) ;
205193}
206194
207195//
@@ -235,3 +223,145 @@ window.onload = function() {
235223 }
236224
237225} ;
226+
227+ // Add scroll behavior to hide topbar when scrolled down beyond a threshold
228+ function addScrollTopBehavior ( ) {
229+ var ticking = false ;
230+ var threshold = 20 ; // px tolerance; adjustable (top and bottom)
231+
232+ // Cache last states to avoid redundant DOM writes
233+ var lastTopbarVisible = null ;
234+ var lastHeaderVisible = null ;
235+ var lastScrollY = window . scrollY || window . pageYOffset || 0 ;
236+ var minDelta = 6 ; // px minimal upward movement to trigger show mid-page
237+ var lastVisible = null ; // persistent desired visibility state
238+
239+ function isTopbarMenuOpen ( ) {
240+ var navItems = document . getElementById ( "nav-items" ) ;
241+ if ( ! navItems ) return false ;
242+ // On mobile, nav is open when it does NOT have 'hidden-on-mobile'
243+ return ! navItems . classList . contains ( "hidden-on-mobile" ) ;
244+ }
245+
246+ function isDocSidebarVisible ( ) {
247+ var sidebar = document . querySelector ( '.docs-sidebar' ) ;
248+ if ( ! sidebar ) return false ;
249+ return sidebar . classList . contains ( 'visible' ) ;
250+ }
251+
252+ function getHeaderEl ( ) {
253+ return document . querySelector ( '#documenter .docs-main header.docs-navbar' ) ;
254+ }
255+
256+ function atTopOrBottom ( tol ) {
257+ var y = window . scrollY || window . pageYOffset || 0 ;
258+ var atTop = y <= tol ;
259+ var atBottom = ( window . innerHeight + y ) >= ( ( document . documentElement && document . documentElement . scrollHeight ) || document . body . offsetHeight ) - tol ;
260+ return { atTop : atTop , atBottom : atBottom , y : y } ;
261+ }
262+
263+ function setHeaderVisible ( visible ) {
264+ var header = getHeaderEl ( ) ;
265+ if ( ! header ) return ;
266+ if ( visible === lastHeaderVisible ) return ;
267+ header . classList . toggle ( 'ct-header-visible' , ! ! visible ) ;
268+ header . classList . toggle ( 'ct-header-hidden' , ! visible ) ;
269+ lastHeaderVisible = visible ;
270+ }
271+
272+ function setTopbarVisible ( visible ) {
273+ if ( visible === lastTopbarVisible ) return ;
274+ if ( visible ) {
275+ showTopBar ( ) ;
276+ } else {
277+ hideTopBar ( ) ;
278+ }
279+ lastTopbarVisible = visible ;
280+ }
281+
282+ function computeDesiredVisibility ( ) {
283+ var pos = atTopOrBottom ( threshold ) ;
284+ var dy = lastScrollY - pos . y ;
285+ var directionUp = dy > minDelta ;
286+ var directionDown = dy < - minDelta ;
287+
288+ // If menus are open, always visible
289+ if ( isTopbarMenuOpen ( ) || isDocSidebarVisible ( ) ) {
290+ return { visible : true , atBottom : false , atTop : pos . atTop , y : pos . y } ;
291+ }
292+
293+ // At top or bottom within threshold => visible
294+ if ( pos . atTop || pos . atBottom ) {
295+ return { visible : true , atBottom : pos . atBottom , atTop : pos . atTop , y : pos . y } ;
296+ }
297+
298+ // Mid-page behavior: show on upward scroll, hide on downward scroll
299+ if ( directionUp ) {
300+ return { visible : true , atBottom : false , atTop : false , y : pos . y } ;
301+ }
302+ if ( directionDown ) {
303+ return { visible : false , atBottom : false , atTop : false , y : pos . y } ;
304+ }
305+
306+ // No significant movement: keep previous state
307+ return { visible : ( lastVisible !== null ? lastVisible : false ) , atBottom : false , atTop : false , y : pos . y } ;
308+ }
309+
310+ function update ( ) {
311+ ticking = false ;
312+ var res = computeDesiredVisibility ( ) ;
313+ var visible = res . visible ;
314+ // Toggle a root class to signal that appearance originates from bottom
315+ // Only set when not forced by menus
316+ var fromBottom = res . atBottom && ! ( isTopbarMenuOpen ( ) || isDocSidebarVisible ( ) ) ;
317+ try {
318+ document . documentElement . classList . toggle ( 'ct-appear-bottom' , ! ! fromBottom ) ;
319+ } catch ( e ) { /* no-op */ }
320+ setTopbarVisible ( visible ) ;
321+ setHeaderVisible ( visible ) ;
322+ // update last scroll position after applying visibility
323+ lastScrollY = res . y ;
324+ lastVisible = visible ;
325+ }
326+
327+ // Initial state: compute once based on current position
328+ update ( ) ;
329+
330+ // Scroll listener
331+ window . addEventListener ( "scroll" , function ( ) {
332+ if ( ! ticking ) {
333+ window . requestAnimationFrame ( update ) ;
334+ ticking = true ;
335+ }
336+ } , { passive : true } ) ;
337+
338+ // Resize listener (in case layout switches around 1055px)
339+ window . addEventListener ( 'resize' , function ( ) {
340+ if ( ! ticking ) {
341+ window . requestAnimationFrame ( update ) ;
342+ ticking = true ;
343+ }
344+ } ) ;
345+
346+ // Click on Documenter burger button: force reevaluation
347+ var docBurger = document . getElementById ( 'documenter-sidebar-button' ) ;
348+ if ( docBurger ) {
349+ docBurger . addEventListener ( 'click' , function ( ) {
350+ // Wait a tick so classes update
351+ setTimeout ( update , 0 ) ;
352+ } ) ;
353+ }
354+
355+ // Observe sidebar visibility class changes
356+ var sidebar = document . querySelector ( '.docs-sidebar' ) ;
357+ if ( sidebar && 'MutationObserver' in window ) {
358+ try {
359+ var observer = new MutationObserver ( function ( ) {
360+ update ( ) ;
361+ } ) ;
362+ observer . observe ( sidebar , { attributes : true , attributeFilter : [ 'class' ] } ) ;
363+ } catch ( e ) {
364+ // no-op
365+ }
366+ }
367+ }
0 commit comments