feat: enhance day detail panel functionality and user experience
All checks were successful
CI / lint-and-test (push) Successful in 14s

- Added functionality to lock the background scroll when the day detail panel is open, improving user interaction by preventing background movement.
- Implemented logic to restore the scroll position when the panel is closed, ensuring a seamless user experience.
- Updated CSS to support the new behavior, enhancing the visual consistency of the day detail panel.
- Added early return checks in navigation button event listeners to prevent actions while the day detail panel is open, improving performance and usability.
This commit is contained in:
2026-02-19 16:33:22 +03:00
parent dee1d776c3
commit 4afd0ca5cc
3 changed files with 23 additions and 0 deletions

View File

@@ -17,6 +17,8 @@ let panelEl = null;
let overlayEl = null; let overlayEl = null;
/** @type {((e: MouseEvent) => void)|null} */ /** @type {((e: MouseEvent) => void)|null} */
let popoverCloseHandler = null; let popoverCloseHandler = null;
/** Scroll position saved when sheet opens (for restore on close). */
let sheetScrollY = 0;
/** /**
* Parse JSON from data attribute (values are stored with " for safety). * Parse JSON from data attribute (values are stored with " for safety).
@@ -172,6 +174,11 @@ function showAsBottomSheet() {
panelEl.style.right = ""; panelEl.style.right = "";
panelEl.style.bottom = "0"; panelEl.style.bottom = "0";
panelEl.hidden = false; panelEl.hidden = false;
sheetScrollY = window.scrollY;
document.body.classList.add("day-detail-sheet-open");
document.body.style.top = "-" + sheetScrollY + "px";
const closeBtn = panelEl.querySelector(".day-detail-close"); const closeBtn = panelEl.querySelector(".day-detail-close");
if (closeBtn) closeBtn.focus(); if (closeBtn) closeBtn.focus();
} }
@@ -204,6 +211,11 @@ export function hideDayDetail() {
document.removeEventListener("click", popoverCloseHandler); document.removeEventListener("click", popoverCloseHandler);
popoverCloseHandler = null; popoverCloseHandler = null;
} }
if (document.body.classList.contains("day-detail-sheet-open")) {
document.body.classList.remove("day-detail-sheet-open");
document.body.style.top = "";
window.scrollTo(0, sheetScrollY);
}
if (panelEl) panelEl.hidden = true; if (panelEl) panelEl.hidden = true;
if (overlayEl) overlayEl.hidden = true; if (overlayEl) overlayEl.hidden = true;
} }

View File

@@ -178,6 +178,7 @@ async function loadMonth() {
if (prevBtn) { if (prevBtn) {
prevBtn.addEventListener("click", () => { prevBtn.addEventListener("click", () => {
if (document.body.classList.contains("day-detail-sheet-open")) return;
if (accessDeniedEl && !accessDeniedEl.hidden) return; if (accessDeniedEl && !accessDeniedEl.hidden) return;
state.current.setMonth(state.current.getMonth() - 1); state.current.setMonth(state.current.getMonth() - 1);
loadMonth(); loadMonth();
@@ -185,6 +186,7 @@ if (prevBtn) {
} }
if (nextBtn) { if (nextBtn) {
nextBtn.addEventListener("click", () => { nextBtn.addEventListener("click", () => {
if (document.body.classList.contains("day-detail-sheet-open")) return;
if (accessDeniedEl && !accessDeniedEl.hidden) return; if (accessDeniedEl && !accessDeniedEl.hidden) return;
state.current.setMonth(state.current.getMonth() + 1); state.current.setMonth(state.current.getMonth() + 1);
loadMonth(); loadMonth();
@@ -211,6 +213,7 @@ if (nextBtn) {
"touchend", "touchend",
(e) => { (e) => {
if (e.changedTouches.length === 0) return; if (e.changedTouches.length === 0) return;
if (document.body.classList.contains("day-detail-sheet-open")) return;
if (accessDeniedEl && !accessDeniedEl.hidden) return; if (accessDeniedEl && !accessDeniedEl.hidden) return;
const t = e.changedTouches[0]; const t = e.changedTouches[0];
const deltaX = t.clientX - startX; const deltaX = t.clientX - startX;

View File

@@ -212,6 +212,14 @@ body {
} }
/* === Day detail panel (popover / bottom sheet) */ /* === Day detail panel (popover / bottom sheet) */
/* Блокировка фона при открытом bottom sheet: прокрутка и свайпы отключены */
body.day-detail-sheet-open {
position: fixed;
left: 0;
right: 0;
overflow: hidden;
}
.day-detail-overlay { .day-detail-overlay {
position: fixed; position: fixed;
inset: 0; inset: 0;