feat(core): hide navigation on scroll down

This commit is contained in:
alistair3149 2022-11-09 20:02:21 -05:00
parent 4583d1283d
commit 6b13da3318
No known key found for this signature in database
5 changed files with 85 additions and 10 deletions

View file

@ -1,24 +1,56 @@
/**
* Create an observer for showing/hiding feature and for firing scroll event hooks.
* Create an observer based vertical scroll direction
*
* @param {Function} onScrollDown functionality for when viewport is scrolled down
* @param {Function} onScrollUp functionality for when viewport is scrolled up
* @param {number} threshold minimum scrolled px to trigger the function
* @return {void}
*/
function initDirectionObserver( onScrollDown, onScrollUp, threshold ) {
const throttle = require( 'mediawiki.util' ).throttle;
let lastScrollTop = window.scrollY;
const onScroll = () => {
const scrollTop = window.scrollY;
if ( Math.abs( scrollTop - lastScrollTop ) < threshold ) {
return;
}
if ( scrollTop > lastScrollTop ) {
onScrollDown();
} else {
onScrollUp();
}
lastScrollTop = scrollTop;
};
window.addEventListener( 'scroll', throttle( onScroll, 250 ) );
}
/**
* Create an observer based on element visiblity.
* Based on Vector
*
* @param {Function} show functionality for when feature is visible
* @param {Function} hide functionality for when feature is hidden
* @param {Function} onHidden functionality for when the element is visible
* @param {Function} onVisible functionality for when the element is hidden
* @return {IntersectionObserver}
*/
function initScrollObserver( show, hide ) {
function initIntersectionObserver( onHidden, onVisible ) {
/* eslint-disable-next-line compat/compat */
return new IntersectionObserver( ( entries ) => {
if ( !entries[ 0 ].isIntersecting && entries[ 0 ].boundingClientRect.top < 0 ) {
// Viewport has crossed the bottom edge of the target element.
show();
onHidden();
} else {
// Viewport is above the bottom edge of the target element.
hide();
onVisible();
}
} );
}
module.exports = {
initScrollObserver
initDirectionObserver,
initIntersectionObserver
};

View file

@ -62,14 +62,27 @@ function uncheckCheckboxHacks() {
* @return {void}
*/
function initStickyHeader( document ) {
const scrollObserver = require( './scrollObserver.js' );
// Detect scroll direction and add the right class
scrollObserver.initDirectionObserver(
() => {
document.body.classList.remove( 'citizen-scroll--up' );
document.body.classList.add( 'citizen-scroll--down' );
},
() => {
document.body.classList.remove( 'citizen-scroll--down' );
document.body.classList.add( 'citizen-scroll--up' );
},
100
);
const sentinel = document.getElementById( 'citizen-body-header-sticky-sentinel' );
// In some pages we use display:none to disable the sticky header
// Do not start observer if it is set to display:none
if ( sentinel && getComputedStyle( sentinel ).getPropertyValue( 'display' ) !== 'none' ) {
const scrollObserver = require( './scrollObserver.js' );
const observer = scrollObserver.initScrollObserver(
const observer = scrollObserver.initIntersectionObserver(
() => {
document.body.classList.add( 'citizen-body-header--sticky' );
},

View file

@ -145,3 +145,14 @@
border-right: 1px solid var( --border-color-base );
}
}
/* Hide header when scroll down on smaller screen sizes */
@media ( max-width: @width-breakpoint-tablet ) {
.citizen-header {
transition: @transition-transform;
}
.citizen-scroll--down .citizen-header {
transform: translateY( 100% );
}
}

View file

@ -65,6 +65,22 @@
}
}
// Hide sticky header on scroll down on smaller screens
@media ( max-width: @width-breakpoint-tablet ) {
.citizen-body-header--sticky {
.mw-body-header {
transition: @transition-transform;
}
&.citizen-scroll--down {
.mw-body-header {
transform: translateY( -100% );
}
}
}
}
// Make sticky header more compact if there are less screen estate
@media ( max-width: @width-breakpoint-tablet ), ( max-height: 800px ) {
.citizen-body-header--sticky {
#siteSub {

View file

@ -191,6 +191,9 @@
"resources/skins.citizen.scripts/search.js",
"resources/skins.citizen.scripts/tableOfContents.js"
],
"dependencies": [
"mediawiki.util"
],
"targets": [
"desktop",
"mobile"