mobile navbar fix

This commit is contained in:
Echo 2025-06-22 12:06:46 -04:00
parent 21a01f4479
commit a29b32712f
No known key found for this signature in database
5 changed files with 128 additions and 10 deletions

View file

@ -12,6 +12,14 @@ main {
transition: margin-left 0.3s ease, max-width 0.3s ease;
}
@media (max-width: 1023px) {
main {
margin-left: 0;
max-width: 100%;
padding: 60px 20px 20px 20px;
}
}
aside.nav, aside[data-nav-target="nav"] {
position: fixed;
left: 0;
@ -24,6 +32,75 @@ aside.nav, aside[data-nav-target="nav"] {
z-index: 1000;
overflow-y: auto;
padding: 24px 8px 24px 8px;
transition: transform 0.3s ease;
}
@media (max-width: 1023px) {
aside.nav, aside[data-nav-target="nav"] {
transform: translateX(-100%);
z-index: 9999;
}
aside.nav.open, aside[data-nav-target="nav"].open {
transform: translateX(0);
box-shadow: 2px 0 20px rgba(0, 0, 0, 0.3);
}
}
.mobile-nav-button {
display: none;
position: fixed;
top: 20px;
left: 20px;
z-index: 100;
background: var(--color-darkless);
color: var(--primary-color);
border: none;
border-radius: 6px;
padding: 12px;
cursor: pointer;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
transition: background-color 0.2s;
}
.mobile-nav-button:hover {
background: #23272a;
}
.mobile-nav-button svg {
width: 24px;
height: 24px;
}
@media (max-width: 1023px) {
.mobile-nav-button {
display: block;
}
}
/* Mobile overlay */
.nav-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(4px);
z-index: 9998;
opacity: 0;
transition: opacity 0.3s ease;
}
.nav-overlay.open {
opacity: 1;
}
@media (max-width: 1023px) {
.nav-overlay.open {
display: block;
}
}
.nav-item, aside[data-nav-target="nav"] .nav-item, aside[data-nav-target="nav"] a.block {

View file

@ -91,4 +91,20 @@
.border-default {
border-color: var(--color-border);
}
.nav-mobile-hidden {
@apply lg:block hidden;
}
.nav-mobile-overlay {
@apply fixed inset-0 bg-black bg-opacity-50 z-40 lg:hidden;
}
.nav-mobile-slide {
@apply transform -translate-x-full lg:translate-x-0 transition-transform duration-300 ease-in-out;
}
.nav-mobile-slide.open {
@apply translate-x-0;
}
}

View file

@ -1,28 +1,39 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["nav", "overlay"]
static targets = ["nav", "overlay", "button"]
toggle() {
const isOpen = this.navTarget.classList.contains("open")
this.navTarget.classList.toggle("open")
this.overlayTarget.classList.toggle("open")
document.body.classList.toggle("overflow-hidden")
if (this.hasButtonTarget) {
this.buttonTarget.setAttribute("aria-expanded", !isOpen)
}
}
close() {
this.navTarget.classList.remove("open")
this.overlayTarget.classList.remove("open")
document.body.classList.remove("overflow-hidden")
if (this.hasButtonTarget) {
this.buttonTarget.setAttribute("aria-expanded", "false")
}
}
clickLink(event) {
// Close nav when clicking links on mobile
if (window.innerWidth <= 768) {
if (window.innerWidth <= 1024) {
this.close()
}
}
resize() {
// Close nav when window is resized to desktop
if (window.innerWidth > 768) {
if (window.innerWidth > 1024) {
this.close()
}
}
@ -30,9 +41,17 @@ export default class extends Controller {
connect() {
// Listen for window resize
window.addEventListener('resize', this.resize.bind(this))
document.addEventListener('keydown', this.handleKeydown.bind(this))
}
disconnect() {
window.removeEventListener('resize', this.resize.bind(this))
document.removeEventListener('keydown', this.handleKeydown.bind(this))
}
handleKeydown(event) {
if (event.key === 'Escape') {
this.close()
}
}
}

View file

@ -139,17 +139,23 @@
<%= Sentry.get_trace_propagation_meta.html_safe %>
</head>
<body class="<%= content_for(:body_class) %>" style="display: flex;" data-controller="nav">
<!-- Mobile nav toggle button -->
<!--<button class="nav-toggle" data-action="click->nav#toggle">Menu</button>-->
<body class="<%= content_for(:body_class) %> flex min-h-screen" data-controller="nav">
<button class="mobile-nav-button"
data-action="click->nav#toggle"
data-nav-target="button"
aria-label="Toggle navigation menu"
aria-expanded="false">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
<!-- Mobile nav overlay -->
<!--<div class="nav-overlay" data-nav-target="overlay" data-action="click->nav#close"></div>-->
<div class="nav-overlay" data-nav-target="overlay" data-action="click->nav#close"></div>
<%= render "shared/nav" %>
<!-- 250px is defined in nav.css -->
<main>
<main class="flex-1 lg:ml-[250px] lg:max-w-[calc(100%-250px)] p-5 mb-[100px] pt-16 lg:pt-5 transition-all duration-300 ease-in-out">
<%= yield %>
<footer>
<div class="container">

View file

@ -1,4 +1,4 @@
<aside class="flex flex-col min-h-screen w-[250px] bg-darkless text-white px-2 py-4 border-r border-default overflow-y-auto" data-nav-target="nav">
<aside class="flex flex-col min-h-screen w-[250px] bg-darkless text-white px-2 py-4 border-r border-default overflow-y-auto lg:block" data-nav-target="nav">
<div class="space-y-4">
<% flash.each do |name, msg| %>
<div>