Merge pull request #37 from PR0M3TH3AN/codex/improve-mobile-ux-for-menu-and-sidebar

Improve mobile sidebar UX
This commit is contained in:
thePR0M3TH3AN
2025-07-10 16:25:54 -04:00
committed by GitHub
4 changed files with 46 additions and 1 deletions

View File

@@ -100,6 +100,19 @@ test('sidebar opens on small screens', async () => {
expect(sidebarLeft).toBe('0px'); expect(sidebarLeft).toBe('0px');
}); });
test('clicking outside closes sidebar on small screens', async () => {
const page = await browser.newPage();
await page.setViewport({ width: 500, height: 800 });
await page.goto(`http://localhost:${port}/`);
await page.waitForSelector('#sidebar-toggle');
await page.click('#sidebar-toggle');
await new Promise(r => setTimeout(r, 300));
await page.click('main');
await new Promise(r => setTimeout(r, 300));
const bodyClass = await page.evaluate(() => document.body.classList.contains('sidebar-open'));
expect(bodyClass).toBe(false);
});
test('sidebar toggles on large screens', async () => { test('sidebar toggles on large screens', async () => {
const page = await browser.newPage(); const page = await browser.newPage();
await page.setViewport({ width: 1024, height: 800 }); await page.setViewport({ width: 1024, height: 800 });

View File

@@ -23,7 +23,9 @@ body {
align-items: center; align-items: center;
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
background: var(--sidebar-bg); background: var(--sidebar-bg);
position: relative; position: sticky;
top: 0;
z-index: 1100;
} }
.search-input { .search-input {
margin-left: auto; margin-left: auto;
@@ -117,6 +119,20 @@ main {
text-decoration: none; text-decoration: none;
color: var(--text-color); color: var(--text-color);
} }
.sidebar-overlay {
display: none;
}
body.sidebar-open .sidebar-overlay {
display: block;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.3);
z-index: 999;
}
@media (max-width: 768px) { @media (max-width: 768px) {
.sidebar { .sidebar {
position: fixed; position: fixed;

View File

@@ -3,6 +3,8 @@ document.addEventListener('DOMContentLoaded', () => {
const themeToggle = document.getElementById('theme-toggle'); const themeToggle = document.getElementById('theme-toggle');
const searchInput = document.getElementById('search-input'); const searchInput = document.getElementById('search-input');
const searchResults = document.getElementById('search-results'); const searchResults = document.getElementById('search-results');
const sidebar = document.getElementById('sidebar');
const sidebarOverlay = document.getElementById('sidebar-overlay');
const root = document.documentElement; const root = document.documentElement;
function setTheme(theme) { function setTheme(theme) {
@@ -20,6 +22,10 @@ document.addEventListener('DOMContentLoaded', () => {
document.body.classList.toggle('sidebar-open'); document.body.classList.toggle('sidebar-open');
}); });
sidebarOverlay?.addEventListener('click', () => {
document.body.classList.remove('sidebar-open');
});
themeToggle?.addEventListener('click', () => { themeToggle?.addEventListener('click', () => {
const next = root.dataset.theme === 'dark' ? 'light' : 'dark'; const next = root.dataset.theme === 'dark' ? 'light' : 'dark';
setTheme(next); setTheme(next);
@@ -76,6 +82,15 @@ document.addEventListener('DOMContentLoaded', () => {
if (!searchResults.contains(e.target) && e.target !== searchInput) { if (!searchResults.contains(e.target) && e.target !== searchInput) {
searchResults.style.display = 'none'; searchResults.style.display = 'none';
} }
if (
window.innerWidth <= 768 &&
document.body.classList.contains('sidebar-open') &&
sidebar &&
!sidebar.contains(e.target) &&
e.target !== sidebarToggle
) {
document.body.classList.remove('sidebar-open');
}
}); });
// breadcrumbs // breadcrumbs

View File

@@ -8,6 +8,7 @@
</head> </head>
<body> <body>
{% include "partials/header.njk" %} {% include "partials/header.njk" %}
<div id="sidebar-overlay" class="sidebar-overlay"></div>
<div class="container"> <div class="container">
{% include "partials/sidebar.njk" %} {% include "partials/sidebar.njk" %}
<main id="content"> <main id="content">