From c47730f2cc8becbd57975da07b6e84184efe7326 Mon Sep 17 00:00:00 2001 From: Viktor Lofgren Date: Tue, 9 Jan 2024 13:30:30 +0100 Subject: [PATCH] (search) Mobile UX improvements. Swipe right to show filter menu. Fix CSS bug that caused parts of the menu to not have a background. --- .../src/main/resources/static/search/menu.js | 75 ++++++++++++++++--- .../main/resources/static/search/serp.scss | 1 - 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/code/services-application/search-service/src/main/resources/static/search/menu.js b/code/services-application/search-service/src/main/resources/static/search/menu.js index a8b4c0b3..5832fd36 100644 --- a/code/services-application/search-service/src/main/resources/static/search/menu.js +++ b/code/services-application/search-service/src/main/resources/static/search/menu.js @@ -1,3 +1,26 @@ +function hideMenu() { + document.getElementById('filters').style.display = 'none'; +} +function showMenu() { + document.getElementById('filters').style.display = 'block'; + + // Defer creation of the close button until the menu is opened. This is needed because the script for creating + // the filter button is run early to avoid layout shifts. + + if (document.getElementById('menu-close') === null) { + registerCloseButton(); + } + + document.getElementById('filters').style.display = 'block'; + + // scroll to the top of the page so the user can see the filters + window.scrollTo({ + top: 0, + left: 0, + behavior: "instant", + }); +} + const registerCloseButton = () => { // Add a button to close the filters for mobile; we do this in js to not pollute the DOM for text-only browsers const closeButton = document.createElement('button'); @@ -6,7 +29,7 @@ const registerCloseButton = () => { closeButton.setAttribute('aria-controls', '#filters'); closeButton.innerHTML = 'X'; closeButton.onclick = (event) => { - document.getElementById('filters').style.display = 'none'; + hideMenu(); event.stopPropagation(); return false; } @@ -20,15 +43,49 @@ filtersButton.setAttribute('aria-controls', '#filters'); filtersButton.innerHTML = 'Ξ'; filtersButton.setAttribute('title', 'Open the filters menu'); filtersButton.onclick = (event) => { - // Defer creation of the close button until the menu is opened. This is needed because the script for creating - // the filter button is run early to avoid layout shifts. - - if (document.getElementById('menu-close') === null) { - registerCloseButton(); - } - - document.getElementById('filters').style.display = 'block'; + showMenu(); event.stopPropagation(); return false; } + document.getElementById('search-box').getElementsByTagName('h1')[0].append(filtersButton); + +// swipe affordances for mobile +if (window.matchMedia('(pointer: coarse)').matches) { + // capture swipes to the left and right to open and close the filters + let touchStartX = 0; + let touchEndX = 0; + let touchStartY = 0; + let touchEndY = 0; + + const swipeThreshold = 100; + const maxVerticalDistance = 75; + document.addEventListener('touchstart', (event) => { + touchStartX = event.changedTouches[0].screenX; + touchStartY = event.changedTouches[0].screenY; + }); + document.addEventListener('touchend', (event) => { + touchEndX = event.changedTouches[0].screenX; + touchEndY = event.changedTouches[0].screenY; + let verticalDistance = Math.abs(touchStartY - touchEndY); + + if (verticalDistance > maxVerticalDistance) { + return; + } + + if (touchEndX - touchStartX > swipeThreshold) { + showMenu(); + event.stopPropagation(); + } else if (touchStartX - touchEndX > swipeThreshold) { + hideMenu(); + event.stopPropagation(); + } + }); + + + // Add a floating panel to the bottom of the page to show a message when the filters are hidden + const floatingPanel = document.createElement('div'); + floatingPanel.setAttribute('style', 'position: fixed; bottom: 0; left: 0; right: 0; background-color: #fff; padding: 1em; text-align: center; display: block; border-top: 1px solid #ccc; box-shadow: 0 0 -5px #eee;'); + floatingPanel.innerHTML = '← right/left open/close the filters →'; + document.body.appendChild(floatingPanel); +} \ No newline at end of file diff --git a/code/services-application/search-service/src/main/resources/static/search/serp.scss b/code/services-application/search-service/src/main/resources/static/search/serp.scss index 3ab845bc..0c44415c 100644 --- a/code/services-application/search-service/src/main/resources/static/search/serp.scss +++ b/code/services-application/search-service/src/main/resources/static/search/serp.scss @@ -668,7 +668,6 @@ footer { top: 0; left: 0; width: 100%; - height: 100%; margin: 0; padding: 0; z-index: 100;