From 7113fab4458c8241d25199f94f9021395f0fbf4c Mon Sep 17 00:00:00 2001 From: Dave Gallant Date: Mon, 16 Feb 2026 18:29:48 -0500 Subject: [PATCH] Add hamburger icon for mobile --- src/App.vue | 56 ++++++++++++++++++++++++++++++++--- src/theme.css | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 4 deletions(-) diff --git a/src/App.vue b/src/App.vue index 41fc9c5..eaac37d 100644 --- a/src/App.vue +++ b/src/App.vue @@ -64,12 +64,14 @@ export default { darkModeQuery: null, themeChangeHandler: null, isLoading: false, + menuOpen: false, }; }, mounted() { window.addEventListener("keydown", this.handleKeyDown); window.addEventListener("resize", this.handleResize); + window.addEventListener("click", this.handleClickOutside); this.detectMobile(); this.fetchDeals(); this.initializeSortMethod(); @@ -81,6 +83,7 @@ export default { beforeUnmount() { window.removeEventListener("keydown", this.handleKeyDown); window.removeEventListener("resize", this.handleResize); + window.removeEventListener("click", this.handleClickOutside); if (this.darkModeQuery && this.themeChangeHandler) { this.darkModeQuery.removeEventListener("change", this.themeChangeHandler); } @@ -331,6 +334,25 @@ export default { localStorage.setItem("viewMode", this.viewMode); }, + toggleMenu() { + this.menuOpen = !this.menuOpen; + }, + + closeMenu() { + this.menuOpen = false; + }, + + handleMenuAction(action) { + action(); + this.closeMenu(); + }, + + handleClickOutside(event) { + if (this.menuOpen && !event.target.closest('.mobile-menu-wrapper')) { + this.closeMenu(); + } + }, + getDealerColor(dealerName) { if (!dealerName) return null; const isDark = document.documentElement.getAttribute('data-bs-theme') === 'dark' || @@ -376,18 +398,44 @@ export default { @keyup.esc="$refs.filterInput.blur()" /> - - - - + + +
+ +
+ + + + +
+
diff --git a/src/theme.css b/src/theme.css index 3b950bd..183fc27 100644 --- a/src/theme.css +++ b/src/theme.css @@ -154,6 +154,88 @@ a:visited { align-items: center; } +@media (max-width: 768px) { + .header-controls { + gap: 8px; + } +} + +/* ============================================ + Responsive Visibility + ============================================ */ + +.desktop-only { + display: inline-flex; +} + +.mobile-only { + display: none; +} + +@media (max-width: 768px) { + .desktop-only { + display: none !important; + } + + .mobile-only { + display: block; + } +} + +/* ============================================ + Mobile Menu + ============================================ */ + +.mobile-menu-wrapper { + position: relative; +} + +.mobile-dropdown { + position: absolute; + top: calc(100% + 8px); + right: 0; + background-color: var(--bg-secondary); + border: 1px solid var(--border-color-light); + border-radius: 8px; + box-shadow: 0 4px 12px var(--shadow-medium); + min-width: 180px; + z-index: 100; + overflow: hidden; +} + +.dropdown-item { + display: flex; + align-items: center; + gap: 10px; + width: 100%; + padding: 12px 14px; + border: none; + background: transparent; + color: var(--text-primary); + font-size: 14px; + cursor: pointer; + transition: background-color 0.2s ease; + text-align: left; +} + +.dropdown-item:hover { + background-color: var(--bg-input); +} + +.dropdown-item:active { + background-color: var(--border-color-light); +} + +.dropdown-item:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.dropdown-item .material-symbols-outlined { + font-size: 20px; + color: var(--text-secondary); +} + /* ============================================ Search Input ============================================ */