From c93833c8063d185e47fdc7be6bcc8af5f6356145 Mon Sep 17 00:00:00 2001 From: shubham Date: Sun, 9 Feb 2025 13:41:35 +0530 Subject: [PATCH 1/2] Remove: code formatters, Add: Table of content component on 4x api page --- _includes/api/en/4x/menu.md | 4 +- css/dark-theme.css | 8 ++++ css/style.css | 95 +++++++++++++++++++++++++++++++++---- js/menu.js | 90 ++++++++++++++++++++++++++++++++++- 4 files changed, 186 insertions(+), 11 deletions(-) diff --git a/_includes/api/en/4x/menu.md b/_includes/api/en/4x/menu.md index ff585b2905..8981def565 100644 --- a/_includes/api/en/4x/menu.md +++ b/_includes/api/en/4x/menu.md @@ -1,5 +1,5 @@ + diff --git a/css/dark-theme.css b/css/dark-theme.css index cded8e8355..0209b027d9 100644 --- a/css/dark-theme.css +++ b/css/dark-theme.css @@ -278,3 +278,11 @@ html.dark-mode #blog-side-menu-container h3 a{ html.dark-mode #blog-side-menu > li > a{ color: var(--dark_inner_text); } + +@media all and (max-width: 1440px) { + html.dark-mode #menu, + #tags-side-menu, + #blog-side-menu-container { + background-color: var(--second_dark_bg); + } +} \ No newline at end of file diff --git a/css/style.css b/css/style.css index 014998840f..ca663dface 100644 --- a/css/style.css +++ b/css/style.css @@ -705,12 +705,12 @@ footer { #blog-side-menu-container { position: fixed; margin: 0; - padding: 0 10px 0 0; + padding: 0; top: 153px; - left: 30px; + right: 0; height: 500px; text-align: left; - font-size: 13px; + font-size: 1rem; overflow-y: auto; } @@ -840,9 +840,82 @@ h2 a { } } +/* table of content btn */ +#menu-toggle { + cursor: pointer; + display: none; + margin-block: 1.5rem; + font-size: 1rem; + padding: 0.5rem; + opacity: 0; +} + +/* responsive */ + +@media all and (max-width: 1440px) { + #menu, + #tags-side-menu, + #blog-side-menu-container { + position: sticky; + max-height: 0; + top: 57px; + left: 0; + background-color: #eee; + z-index: 100; + } + + #menu.open { + max-height: 50vh; + padding: 1rem; + } + + #menu-toggle.show{ + display: block; + opacity: 1; + } + + #menu-toggle.position-fixed { + position: fixed; + right: 1rem; + top: 57px; + margin-block: 1rem; + border-radius: 50%; + background-color: #eeeeee56; + padding: 1rem; + border: 1px solid rgb(202, 199, 199); + display: flex; + justify-content: center; + align-items: center; + } + + .content { + margin: 57px 3% 7%; + } + + #menu li { + cursor: pointer; + border-bottom: 1px solid #cdcdcd; + } + + #overlay.blurs{ + display: block; + } +} + /* responsive */ @media all and (max-width: 1110px) { + #menu, + #tags-side-menu, + #blog-side-menu-container { + position: fixed; + border-bottom: 1px solid #ddd; + } + + .content { + margin: 80px 3% 7%; + } + #boxes { grid-template-columns: 1fr 1fr; } @@ -908,12 +981,6 @@ h2 a { font-weight: normal; } - #menu, - #tags-side-menu, - #blog-side-menu-container { - display: none; - } - .content { padding-left: 0; } @@ -1020,6 +1087,16 @@ h2 a { #boxes { grid-template-columns: 1fr; } + + #menu-toggle.position-fixed { + left: 0; + top: 57px; + margin-block: 0rem; + width: 100vw; + padding: 0.5rem; + border-radius: 0; + background-color: #eeeeeec9; + } } @media all and (max-width: 420px) { diff --git a/js/menu.js b/js/menu.js index 6ac26f02b7..01c4c8cc34 100644 --- a/js/menu.js +++ b/js/menu.js @@ -115,4 +115,92 @@ overlay?.addEventListener("click", () => { document .querySelector(`.submenu-content a[href="${document.location.pathname}"]`) - ?.classList.add("current"); \ No newline at end of file + ?.classList.add("current"); + +// TOC +const tocScreen = window.matchMedia("(max-width: 1440px)"); +let isTocScreen = tocScreen.matches; +const toggleBtn = document.getElementById("menu-toggle"); +const menuList = document.getElementById("menu"); +// ! important note add scroll observer element common to all pages that include TOC component 👇🏻 remove id to "scroll-obsever" +const firstHeader = document.getElementById("express"); +let observer; + + +// Scroll observer (perform better than window scroll event listener) +function createScrollObserver() { + if (observer) observer.disconnect(); + + let options = { + root: null, // Observe relative to viewport + rootMargin: "-57px 0px 0px 0px", // Slight offset to ensure intersection triggers correctly + threshold: 0, // Trigger when the element is fully out of view (i.e. behind header) + }; + + observer = new IntersectionObserver(handleIntersect, options); + // observe intersection of TOC btn with header bar + observer.observe(firstHeader); +} + +// Update button visibility based on screen size +function updateButtonVisibility() { + if (isTocScreen) { + toggleBtn?.classList.add("show"); + createScrollObserver(); + } else { + toggleBtn?.classList.remove("show"); + if (observer) observer.disconnect(); + } + } + +function handleIntersect(entries) { + const [entry] = entries + const clientWidth = entry.boundingClientRect.width + // first header in invisible then show floating TOC btn + if(!entry.isIntersecting) { + if(toggleBtn) { + if(clientWidth >= 540) { + toggleBtn.innerHTML = "▼"; + } else { + toggleBtn.innerHTML = "Table of content ▼"; + }; + } + toggleBtn?.classList.add("position-fixed"); + }; + // first header is visible then show static TOC btn + if(entry.isIntersecting) { + if(toggleBtn) toggleBtn.innerHTML = "Table of content ▼"; + toggleBtn?.classList.remove("position-fixed"); + }; +}; + +// Show button on page load +updateButtonVisibility(); + +// Listen for changes in screen size +tocScreen.addEventListener("change", (event) => { + isTocScreen = event.matches; + updateButtonVisibility(); +}); + +// Toggle menu on button click +toggleBtn?.addEventListener("click", () => { + menuList?.classList.toggle("open"); + overlay?.classList.toggle("blurs"); + document.body.classList.toggle("no-scroll"); + if (isTocScreen) { + toggleBtn?.classList.remove("show"); + } +}); + +// Close menu on link click +document.querySelectorAll("#menu a").forEach((link) => { + link.addEventListener("click", function () { + menuList?.classList.remove("open"); + overlay?.classList.remove("blurs"); + document.body.classList.remove("no-scroll"); + if (isTocScreen) { + toggleBtn?.classList.add("show"); + } + }); +}); From 9dc44b9ec07521f293427c9f4aeda24b613428b6 Mon Sep 17 00:00:00 2001 From: shubham Date: Mon, 10 Feb 2025 09:37:26 +0530 Subject: [PATCH 2/2] fix toc clash with header nav btns --- js/menu.js | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/js/menu.js b/js/menu.js index 01c4c8cc34..ebf5259477 100644 --- a/js/menu.js +++ b/js/menu.js @@ -48,6 +48,8 @@ const menu = document.querySelector("#navmenu"); const overlay = document.querySelector("#overlay"); const navButton = document.querySelector("#nav-button"); const languagePickerButton = document.querySelector("#language-picker-button"); +const toggleBtn = document.getElementById("menu-toggle"); +const menuList = document.getElementById("menu"); for (const el of linkItemsMenu) { el.addEventListener("click", (e) => { @@ -83,6 +85,7 @@ navButton?.addEventListener("click", () => { languagePickerMenu?.classList.remove("opens"); menu?.classList.toggle("opens"); } else { + updateTocVisibility(); menu?.classList.toggle("opens"); overlay?.classList.toggle("blurs"); document.body.classList.toggle("no-scroll"); @@ -96,6 +99,7 @@ languagePickerButton?.addEventListener("click", () => { menu?.classList.remove("opens"); languagePickerMenu?.classList.toggle("opens"); } else { + updateTocVisibility(); languagePickerMenu?.classList.toggle("opens"); overlay?.classList.toggle("blurs"); document.body.classList.toggle("no-scroll"); @@ -109,6 +113,11 @@ overlay?.addEventListener("click", () => { if (languagePickerMenu?.classList.contains("opens")) { languagePickerMenu.classList.remove("opens"); } + if(menuList?.classList.contains("open")) { + toggleBtn?.classList.add("show"); + menuList?.classList.remove("open"); + menu.disabled = "false"; + } overlay.classList.remove("blurs"); document.body.classList.remove("no-scroll"); }); @@ -120,9 +129,7 @@ document // TOC const tocScreen = window.matchMedia("(max-width: 1440px)"); let isTocScreen = tocScreen.matches; -const toggleBtn = document.getElementById("menu-toggle"); -const menuList = document.getElementById("menu"); -// ! important note add scroll observer element common to all pages that include TOC component 👇🏻 remove id to "scroll-obsever" +// ! important note add scroll observer element common to all pages that include TOC component 👇🏻 remove id to "scroll-observer" const firstHeader = document.getElementById("express"); let observer; @@ -143,8 +150,10 @@ function createScrollObserver() { } // Update button visibility based on screen size -function updateButtonVisibility() { +function updateTocVisibility() { if (isTocScreen) { + overlay.classList.remove("blurs") + menuList.classList.remove("open"); toggleBtn?.classList.add("show"); createScrollObserver(); } else { @@ -175,12 +184,12 @@ function handleIntersect(entries) { }; // Show button on page load -updateButtonVisibility(); +updateTocVisibility(); // Listen for changes in screen size tocScreen.addEventListener("change", (event) => { isTocScreen = event.matches; - updateButtonVisibility(); + updateTocVisibility(); }); // Toggle menu on button click @@ -188,19 +197,17 @@ toggleBtn?.addEventListener("click", () => { menuList?.classList.toggle("open"); overlay?.classList.toggle("blurs"); document.body.classList.toggle("no-scroll"); - if (isTocScreen) { - toggleBtn?.classList.remove("show"); - } + toggleBtn?.classList.remove("show"); }); // Close menu on link click document.querySelectorAll("#menu a").forEach((link) => { link.addEventListener("click", function () { - menuList?.classList.remove("open"); - overlay?.classList.remove("blurs"); - document.body.classList.remove("no-scroll"); - if (isTocScreen) { - toggleBtn?.classList.add("show"); - } + if(isTocScreen) { + menuList?.classList.remove("open"); + overlay?.classList.remove("blurs"); + document.body.classList.remove("no-scroll"); + toggleBtn?.classList.add("show"); + } }); });