Merge pull request #2246 from thelounge/astorije/sidebar-overlay

Add a semi-opaque overlay when channel list is open on mobile
This commit is contained in:
Pavel Djundik 2018-03-18 18:00:23 +02:00 committed by GitHub
commit 039c12266a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 72 additions and 36 deletions

View File

@ -518,7 +518,7 @@ kbd {
width: 220px; width: 220px;
} }
#sidebar.menu-open { #viewport.menu-open #sidebar {
display: none; display: none;
will-change: transform; will-change: transform;
} }
@ -2273,22 +2273,46 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
height: 100%; height: 100%;
position: absolute; position: absolute;
left: -220px; left: -220px;
z-index: 1; z-index: 2;
transition: transform 160ms; transition: transform 160ms;
transform: translateZ(0); transform: translateZ(0);
} }
#sidebar.menu-open { #sidebar-overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
opacity: 0;
visibility: hidden;
transition: opacity 160ms, visibility 160ms;
z-index: 1;
}
#viewport.menu-open #sidebar-overlay {
opacity: 1;
}
#viewport.menu-open #sidebar {
display: flex; display: flex;
transform: translate3d(220px, 0, 0); transform: translate3d(220px, 0, 0);
} }
#sidebar.menu-dragging { #viewport.menu-dragging #sidebar-overlay,
transition: none !important; #viewport.menu-dragging #sidebar {
transition: none;
} }
#sidebar.menu-open .messages { #viewport.menu-open #sidebar,
pointer-events: none; #viewport.menu-dragging #sidebar {
box-shadow: 0 0 25px 0 rgba(0, 0, 0, 0.5);
}
#viewport.menu-open #sidebar-overlay,
#viewport.menu-dragging #sidebar-overlay {
visibility: visible;
} }
#sidebar .empty::before { #sidebar .empty::before {

View File

@ -44,6 +44,7 @@
<span class="tooltipped tooltipped-n tooltipped-no-touch" aria-label="Sign out"><button class="icon sign-out" id="sign-out" aria-label="Sign out"></button></span> <span class="tooltipped tooltipped-n tooltipped-no-touch" aria-label="Sign out"><button class="icon sign-out" id="sign-out" aria-label="Sign out"></button></span>
</footer> </footer>
</aside> </aside>
<div id="sidebar-overlay"></div>
<article id="windows"> <article id="windows">
<div id="loading" class="window active"> <div id="loading" class="window active">
<div id="loading-status-container"> <div id="loading-status-container">

View File

@ -40,13 +40,17 @@ $(function() {
storage.set(name, state); storage.set(name, state);
} }
$("#windows").on("click", function(e) { // If sidebar overlay is visible and it is clicked, close the sidebar
const isOpen = slideoutMenu.isOpen(); $("#sidebar-overlay").on("click", () => {
slideoutMenu.toggle(false);
storeSidebarVisibility("thelounge.state.sidebar", false);
});
if ((isOpen && $(window).outerWidth() < utils.mobileViewportPixels) || $(e.target).is(".lt")) { $("#windows").on("click", "button.lt", () => {
slideoutMenu.toggle(!isOpen); const isOpen = !slideoutMenu.isOpen();
storeSidebarVisibility("thelounge.state.sidebar", !isOpen);
} slideoutMenu.toggle(isOpen);
storeSidebarVisibility("thelounge.state.sidebar", isOpen);
}); });
viewport.on("click", ".rt", function() { viewport.on("click", ".rt", function() {

View File

@ -1,6 +1,8 @@
"use strict"; "use strict";
const viewport = document.getElementById("viewport");
const menu = document.getElementById("sidebar"); const menu = document.getElementById("sidebar");
const sidebarOverlay = document.getElementById("sidebar-overlay");
let touchStartPos = null; let touchStartPos = null;
let touchCurPos = null; let touchCurPos = null;
@ -16,7 +18,7 @@ class SlideoutMenu {
static toggle(state) { static toggle(state) {
menuIsOpen = state; menuIsOpen = state;
menu.classList.toggle("menu-open", state); viewport.classList.toggle("menu-open", state);
} }
static isOpen() { static isOpen() {
@ -34,46 +36,50 @@ function onTouchStart(e) {
menuWidth = parseFloat(window.getComputedStyle(menu).width); menuWidth = parseFloat(window.getComputedStyle(menu).width);
if ((!menuIsOpen && touch.screenX < 50) || (menuIsOpen && touch.screenX > menuWidth)) { if (!menuIsOpen || touch.screenX > menuWidth) {
touchStartPos = touch; touchStartPos = touch;
touchCurPos = touch; touchCurPos = touch;
touchStartTime = Date.now(); touchStartTime = Date.now();
menu.classList.toggle("menu-dragging", true); document.body.addEventListener("touchmove", onTouchMove, {passive: true});
document.body.addEventListener("touchmove", onTouchMove);
document.body.addEventListener("touchend", onTouchEnd, {passive: true}); document.body.addEventListener("touchend", onTouchEnd, {passive: true});
} }
} }
function onTouchMove(e) { function onTouchMove(e) {
const touch = touchCurPos = e.touches.item(0); const touch = touchCurPos = e.touches.item(0);
let setX = touch.screenX - touchStartPos.screenX; let distX = touch.screenX - touchStartPos.screenX;
const distY = touch.screenY - touchStartPos.screenY;
if (Math.abs(setX > 30)) { if (!menuIsMoving) {
menuIsMoving = true; // tan(45°) is 1. Gestures in 0°-45° (< 1) are considered horizontal, so
} // menu must be open; gestures in 45°-90° (>1) are considered vertical, so
// chat windows must be scrolled.
if (!menuIsMoving && Math.abs(touch.screenY - touchStartPos.screenY) > 30) { if (Math.abs(distY / distX) >= 1) {
onTouchEnd(); onTouchEnd();
return; return;
} }
const devicePixelRatio = window.devicePixelRatio || 2;
if (Math.abs(distX) > devicePixelRatio) {
viewport.classList.toggle("menu-dragging", true);
menuIsMoving = true;
}
}
if (menuIsOpen) { if (menuIsOpen) {
setX += menuWidth; distX += menuWidth;
} }
if (setX > menuWidth) { if (distX > menuWidth) {
setX = menuWidth; distX = menuWidth;
} else if (setX < 0) { } else if (distX < 0) {
setX = 0; distX = 0;
} }
menu.style.transform = "translate3d(" + setX + "px, 0, 0)"; menu.style.transform = "translate3d(" + distX + "px, 0, 0)";
sidebarOverlay.style.opacity = distX / menuWidth;
if (menuIsMoving) {
e.preventDefault();
e.stopPropagation();
}
} }
function onTouchEnd() { function onTouchEnd() {
@ -86,8 +92,9 @@ function onTouchEnd() {
document.body.removeEventListener("touchmove", onTouchMove); document.body.removeEventListener("touchmove", onTouchMove);
document.body.removeEventListener("touchend", onTouchEnd); document.body.removeEventListener("touchend", onTouchEnd);
menu.classList.toggle("menu-dragging", false); viewport.classList.toggle("menu-dragging", false);
menu.style.transform = null; menu.style.transform = null;
sidebarOverlay.style.opacity = null;
touchStartPos = null; touchStartPos = null;
touchCurPos = null; touchCurPos = null;