From 4a548070ae32c56d9dc2a63ba231a5bdf790e9fd Mon Sep 17 00:00:00 2001 From: Lam Nguyen Date: Thu, 15 May 2025 09:20:48 -0700 Subject: [PATCH] Sidebar: Mobile support --- assets/css/v2/style.css | 105 ++++++++++++++++++++++++++++++- assets/js/sidebar-v2.js | 44 +++++++++++++ layouts/_default/docs.html | 5 +- layouts/_default/list.html | 3 +- layouts/partials/breadcrumb.html | 1 + 5 files changed, 153 insertions(+), 5 deletions(-) diff --git a/assets/css/v2/style.css b/assets/css/v2/style.css index e152fca..62bed2b 100644 --- a/assets/css/v2/style.css +++ b/assets/css/v2/style.css @@ -91,6 +91,7 @@ --sidebar-line-box-left: 12px; --sidebar-width: 22rem; --sidebar-line-width: 11.5px; + --sidebar-mobile-top-displacement: 5rem; --side-gutter-width: 20rem; --table-top-bottom-spacing: 1rem; --table-row-space-between: 1.5rem; @@ -266,6 +267,10 @@ header { padding: 20px 10px; } + .nav-item-explore { + margin: 0; + } + .navbar-button { padding: 0.5rem 0.5rem; border: none; @@ -462,6 +467,10 @@ nav { position: relative; z-index: 2; min-height: 74vh; + + .sidebar__mobile__toggle { + display: none; + } } .sidebar-layout::before { @@ -525,8 +534,84 @@ nav { column-gap: var(--grid-column-gutter); } - .sidebar-layout { - display: none; + .content-layout .breadcrumb-layout { + position: sticky; + top: 0; + z-index: 3; + } + + body:has(.sidebar__mobile-open) { + /* Disable scrolling in main content + hide footer if the sidebar is visible */ + overflow-y: hidden; + + .sidebar-layout { + position: absolute; + height: 100%; + } + + footer { + display: none; + } + + .sidebar-layout .sidebar__mobile__toggle { + display: flex; + align-items: center; + position: sticky; + top: 1rem; + margin-top: 2rem; + margin-left: 2rem; + margin-right: 2rem; + padding: 0.5rem; + color: white; + background-color: oklch(var(--color-brand)); + } + } + + .sidebar__mobile__toggle { + background-color: transparent; + border: none; + + .lucide { + margin-right: 1rem; + } + } + + .main-layout { + /* Mobile support for sidebar */ + display: flex; + flex-direction: column; + position: relative; + + .sidebar-layout { + min-height: fit-content; + background: white; + z-index: 999; + width: calc(100% + 4rem); + margin-left: -2rem; + + &::before { + display: none; + } + + nav { + width: 100%; + display: none; + top: var(--sidebar-mobile-top-displacement); + max-height: calc(100vh - var(--sidebar-mobile-top-displacement)); + padding: 0 2rem; + + .sidebar__container { + width: 100%; + } + } + } + + .content-layout { + .breadcrumb-layout .sidebar__mobile__toggle { + display: inline; + padding: 0; + } + } } main { @@ -933,6 +1018,10 @@ button:has(~ .product-selector[style*="none"]) > .product-selector-button-icon { } } +nav.sidebar.sidebar__mobile-open { + display: block; +} + /* MARK: Content */ @@ -941,6 +1030,18 @@ p { line-height: 1.5rem; } +.breadcrumb-layout { + position: relative; + background-color: white; + width: calc(100% + 4rem); + margin-left: -2rem; + padding: 1rem 2rem; + + .sidebar__mobile__toggle { + display: none; + } +} + .breadcrumb { color: var(--color-foreground); text-decoration: none; diff --git a/assets/js/sidebar-v2.js b/assets/js/sidebar-v2.js index a55e256..042d8c6 100644 --- a/assets/js/sidebar-v2.js +++ b/assets/js/sidebar-v2.js @@ -1,5 +1,6 @@ document.addEventListener('click', (e) => { const toggle = e.target.closest('.sidebar__toggle'); + const sidebarMobileToggle = e.target.closest('.sidebar__mobile__toggle'); if (toggle) { const chevron = toggle.querySelector('.sidebar__chevron'); const expanded = toggle.getAttribute('aria-expanded') === 'true'; @@ -14,5 +15,48 @@ document.addEventListener('click', (e) => { if (chevron) { chevron.classList.toggle('sidebar__chevron--open', !expanded); } + } else if (sidebarMobileToggle) { + // Show the sidebar + const sidebar = document.getElementById('sidebar-v2'); + const expanded = + sidebarMobileToggle.getAttribute('aria-expanded') === 'true'; + + if (!expanded) { + sidebar.classList.add('sidebar__mobile-open'); + } else { + sidebar.classList.remove('sidebar__mobile-open'); + } + + // Set the aria for all the toggle buttons so they are in lockstep + const toggleButtons = document.getElementsByClassName( + 'sidebar__mobile__toggle' + ); + for (const button of [...toggleButtons]) { + button.setAttribute('aria-expanded', String(!expanded)); + } } }); + +const debounce = (callback, wait) => { + let timeoutId = null; + return (...args) => { + window.clearTimeout(timeoutId); + timeoutId = window.setTimeout(() => { + callback(...args); + }, wait); + }; +}; + +window.addEventListener( + 'resize', + debounce(() => { + const sidebar = document.getElementById('sidebar-v2'); + + if ( + window.innerWidth > 88 * 16 && + sidebar.classList.contains('sidebar__mobile-open') + ) { + sidebar.classList.remove('sidebar__mobile-open'); + } + }, 200) +); diff --git a/layouts/_default/docs.html b/layouts/_default/docs.html index 43b4d6e..3b66e9a 100644 --- a/layouts/_default/docs.html +++ b/layouts/_default/docs.html @@ -69,14 +69,15 @@
-
+ +
{{ partial "sidebar-v2.html" . }}
-
+
{{ if not .IsHome }} {{ if not (in .Params.display_breadcrumb "false" ) }} {{ partial "breadcrumb" .}} diff --git a/layouts/_default/list.html b/layouts/_default/list.html index 8d9fd72..badaade 100644 --- a/layouts/_default/list.html +++ b/layouts/_default/list.html @@ -13,6 +13,7 @@
+
{{ partial "sidebar-v2.html" . }}
@@ -20,7 +21,7 @@
-
+
{{ if not .IsHome }} {{ if not (in .Params.display_breadcrumb "false" ) }} {{ partial "breadcrumb" .}} diff --git a/layouts/partials/breadcrumb.html b/layouts/partials/breadcrumb.html index eeba1ad..c60e52c 100644 --- a/layouts/partials/breadcrumb.html +++ b/layouts/partials/breadcrumb.html @@ -1,6 +1,7 @@
    +
  1. Home
  2. {{- define "breadcrumb" -}} {{- with .Parent -}}