ui: improve menu folding (#989)
* ui: improve menu folding Fold/unfold the menu bar just by the amount of scroll, not by its full width * refactor: use a variable for the menu bar height * Fix menu scroll jittering, remove hover folding smoothness Rewrite it to use `position:` `sticky` and `relative` instead of continuous programmatic position changes On-hover folding-unfolding transition removal is a side-effect
This commit is contained in:
parent
ca4b85b815
commit
fd56a53e76
|
@ -580,26 +580,60 @@ function playpen_text(playpen) {
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(function autoHideMenu() {
|
(function controllMenu() {
|
||||||
var menu = document.getElementById('menu-bar');
|
var menu = document.getElementById('menu-bar');
|
||||||
|
|
||||||
var previousScrollTop = document.scrollingElement.scrollTop;
|
(function controllPosition() {
|
||||||
|
var scrollTop = document.scrollingElement.scrollTop;
|
||||||
document.addEventListener('scroll', function () {
|
var prevScrollTop = scrollTop;
|
||||||
if (menu.classList.contains('folded') && document.scrollingElement.scrollTop < previousScrollTop) {
|
var minMenuY = -menu.clientHeight - 50;
|
||||||
menu.classList.remove('folded');
|
// When the script loads, the page can be at any scroll (e.g. if you reforesh it).
|
||||||
} else if (!menu.classList.contains('folded') && document.scrollingElement.scrollTop > previousScrollTop) {
|
menu.style.top = scrollTop + 'px';
|
||||||
menu.classList.add('folded');
|
// Same as parseInt(menu.style.top.slice(0, -2), but faster
|
||||||
}
|
var topCache = menu.style.top.slice(0, -2);
|
||||||
|
menu.classList.remove('sticky');
|
||||||
if (!menu.classList.contains('bordered') && document.scrollingElement.scrollTop > 0) {
|
var stickyCache = false; // Same as menu.classList.contains('sticky'), but faster
|
||||||
menu.classList.add('bordered');
|
document.addEventListener('scroll', function () {
|
||||||
}
|
scrollTop = Math.max(document.scrollingElement.scrollTop, 0);
|
||||||
|
// `null` means that it doesn't need to be updated
|
||||||
if (menu.classList.contains('bordered') && document.scrollingElement.scrollTop === 0) {
|
var nextSticky = null;
|
||||||
menu.classList.remove('bordered');
|
var nextTop = null;
|
||||||
}
|
var scrollDown = scrollTop > prevScrollTop;
|
||||||
|
var menuPosAbsoluteY = topCache - scrollTop;
|
||||||
previousScrollTop = Math.max(document.scrollingElement.scrollTop, 0);
|
if (scrollDown) {
|
||||||
}, { passive: true });
|
nextSticky = false;
|
||||||
|
if (menuPosAbsoluteY > 0) {
|
||||||
|
nextTop = prevScrollTop;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (menuPosAbsoluteY > 0) {
|
||||||
|
nextSticky = true;
|
||||||
|
} else if (menuPosAbsoluteY < minMenuY) {
|
||||||
|
nextTop = prevScrollTop + minMenuY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nextSticky === true && stickyCache === false) {
|
||||||
|
menu.classList.add('sticky');
|
||||||
|
stickyCache = true;
|
||||||
|
} else if (nextSticky === false && stickyCache === true) {
|
||||||
|
menu.classList.remove('sticky');
|
||||||
|
stickyCache = false;
|
||||||
|
}
|
||||||
|
if (nextTop !== null) {
|
||||||
|
menu.style.top = nextTop + 'px';
|
||||||
|
topCache = nextTop;
|
||||||
|
}
|
||||||
|
prevScrollTop = scrollTop;
|
||||||
|
}, { passive: true });
|
||||||
|
})();
|
||||||
|
(function controllBorder() {
|
||||||
|
menu.classList.remove('bordered');
|
||||||
|
document.addEventListener('scroll', function () {
|
||||||
|
if (menu.offsetTop === 0) {
|
||||||
|
menu.classList.remove('bordered');
|
||||||
|
} else {
|
||||||
|
menu.classList.add('bordered');
|
||||||
|
}
|
||||||
|
}, { passive: true });
|
||||||
|
})();
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -20,14 +20,13 @@ a > .hljs {
|
||||||
|
|
||||||
/* Menu Bar */
|
/* Menu Bar */
|
||||||
|
|
||||||
#menu-bar {
|
#menu-bar,
|
||||||
position: -webkit-sticky;
|
#menu-bar-hover-placeholder {
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 101;
|
z-index: 101;
|
||||||
margin: auto calc(0px - var(--page-padding));
|
margin: auto calc(0px - var(--page-padding));
|
||||||
}
|
}
|
||||||
#menu-bar > #menu-bar-sticky-container {
|
#menu-bar {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
background-color: var(--bg);
|
background-color: var(--bg);
|
||||||
|
@ -35,10 +34,21 @@ a > .hljs {
|
||||||
border-bottom-width: 1px;
|
border-bottom-width: 1px;
|
||||||
border-bottom-style: solid;
|
border-bottom-style: solid;
|
||||||
}
|
}
|
||||||
.js #menu-bar > #menu-bar-sticky-container {
|
#menu-bar.sticky,
|
||||||
transition: transform 0.3s;
|
.js #menu-bar-hover-placeholder:hover + #menu-bar,
|
||||||
|
.js #menu-bar:hover,
|
||||||
|
.js.sidebar-visible #menu-bar {
|
||||||
|
position: -webkit-sticky;
|
||||||
|
position: sticky;
|
||||||
|
top: 0 !important;
|
||||||
}
|
}
|
||||||
#menu-bar.bordered > #menu-bar-sticky-container {
|
#menu-bar-hover-placeholder {
|
||||||
|
position: sticky;
|
||||||
|
position: -webkit-sticky;
|
||||||
|
top: 0;
|
||||||
|
height: var(--menu-bar-height);
|
||||||
|
}
|
||||||
|
#menu-bar.bordered {
|
||||||
border-bottom-color: var(--table-border-color);
|
border-bottom-color: var(--table-border-color);
|
||||||
}
|
}
|
||||||
#menu-bar i, #menu-bar .icon-button {
|
#menu-bar i, #menu-bar .icon-button {
|
||||||
|
@ -72,10 +82,6 @@ a > .hljs {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
html:not(.sidebar-visible) #menu-bar:not(:hover).folded > #menu-bar-sticky-container {
|
|
||||||
transform: translateY(calc(-10px - var(--menu-bar-height)));
|
|
||||||
}
|
|
||||||
|
|
||||||
.left-buttons {
|
.left-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
|
|
|
@ -60,6 +60,7 @@ h4 a.header:target {
|
||||||
.page {
|
.page {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
padding: 0 var(--page-padding);
|
padding: 0 var(--page-padding);
|
||||||
|
margin-top: calc(0px - var(--menu-bar-height)); /* Compensate for the #menu-bar-hover-placeholder */
|
||||||
}
|
}
|
||||||
.page-wrapper {
|
.page-wrapper {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
|
@ -97,41 +97,40 @@
|
||||||
|
|
||||||
<div class="page">
|
<div class="page">
|
||||||
{{> header}}
|
{{> header}}
|
||||||
<div id="menu-bar" class="menu-bar">
|
<div id="menu-bar-hover-placeholder"></div>
|
||||||
<div id="menu-bar-sticky-container">
|
<div id="menu-bar" class="menu-bar sticky bordered">
|
||||||
<div class="left-buttons">
|
<div class="left-buttons">
|
||||||
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||||||
<i class="fa fa-bars"></i>
|
<i class="fa fa-bars"></i>
|
||||||
</button>
|
</button>
|
||||||
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||||||
<i class="fa fa-paint-brush"></i>
|
<i class="fa fa-paint-brush"></i>
|
||||||
</button>
|
</button>
|
||||||
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||||||
<li role="none"><button role="menuitem" class="theme" id="light">{{ theme_option "Light" }}</button></li>
|
<li role="none"><button role="menuitem" class="theme" id="light">{{ theme_option "Light" }}</button></li>
|
||||||
<li role="none"><button role="menuitem" class="theme" id="rust">{{ theme_option "Rust" }}</button></li>
|
<li role="none"><button role="menuitem" class="theme" id="rust">{{ theme_option "Rust" }}</button></li>
|
||||||
<li role="none"><button role="menuitem" class="theme" id="coal">{{ theme_option "Coal" }}</button></li>
|
<li role="none"><button role="menuitem" class="theme" id="coal">{{ theme_option "Coal" }}</button></li>
|
||||||
<li role="none"><button role="menuitem" class="theme" id="navy">{{ theme_option "Navy" }}</button></li>
|
<li role="none"><button role="menuitem" class="theme" id="navy">{{ theme_option "Navy" }}</button></li>
|
||||||
<li role="none"><button role="menuitem" class="theme" id="ayu">{{ theme_option "Ayu" }}</button></li>
|
<li role="none"><button role="menuitem" class="theme" id="ayu">{{ theme_option "Ayu" }}</button></li>
|
||||||
</ul>
|
</ul>
|
||||||
{{#if search_enabled}}
|
{{#if search_enabled}}
|
||||||
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
||||||
<i class="fa fa-search"></i>
|
<i class="fa fa-search"></i>
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 class="menu-title">{{ book_title }}</h1>
|
<h1 class="menu-title">{{ book_title }}</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="{{ path_to_root }}print.html" title="Print this book" aria-label="Print this book">
|
<a href="{{ path_to_root }}print.html" title="Print this book" aria-label="Print this book">
|
||||||
<i id="print-button" class="fa fa-print"></i>
|
<i id="print-button" class="fa fa-print"></i>
|
||||||
</a>
|
</a>
|
||||||
{{#if git_repository_url}}
|
{{#if git_repository_url}}
|
||||||
<a href="{{git_repository_url}}" title="Git repository" aria-label="Git repository">
|
<a href="{{git_repository_url}}" title="Git repository" aria-label="Git repository">
|
||||||
<i id="git-repository-button" class="fa {{git_repository_icon}}"></i>
|
<i id="git-repository-button" class="fa {{git_repository_icon}}"></i>
|
||||||
</a>
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue