From a5c5a9349ffff06c52af4abdc27709bc4b19f0b5 Mon Sep 17 00:00:00 2001 From: pavel Date: Wed, 11 Feb 2026 18:54:12 +0100 Subject: [PATCH] mobile friendly --- frontend/index.html | 8 +++ frontend/src/main.js | 25 ++++++++ frontend/src/style.css | 142 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) diff --git a/frontend/index.html b/frontend/index.html index 5be239e..c9b08bb 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -54,6 +54,14 @@ +
+ + +
⌘
diff --git a/frontend/src/main.js b/frontend/src/main.js index 91e3ffd..edf3959 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -60,6 +60,9 @@ const chatForm = document.getElementById('chat-form'); const chatInput = document.getElementById('chat-input'); const clearChatBtn = document.getElementById('clear-chat-btn'); const chatSendBtn = document.getElementById('chat-send-btn'); +const sidebarEl = document.querySelector('.sidebar'); +const menuToggle = document.getElementById('menu-toggle'); +const sidebarOverlay = document.getElementById('sidebar-overlay'); function updateState(newState) { Object.assign(state, newState); @@ -240,6 +243,11 @@ function selectTask(id, runId = null) { renderTaskList(); renderRunHistory(task); showTaskView(task); + + // Close sidebar on mobile after selection + if (window.innerWidth <= 768) { + closeMobileMenu(); + } } function renderRunHistory(task) { @@ -753,6 +761,23 @@ document.querySelectorAll('.tab-btn').forEach(btn => { }); }); +function toggleMobileMenu() { + sidebarEl.classList.toggle('open'); + menuToggle.classList.toggle('active'); + sidebarOverlay.classList.toggle('hidden'); + document.body.style.overflow = sidebarEl.classList.contains('open') ? 'hidden' : ''; +} + +function closeMobileMenu() { + sidebarEl.classList.remove('open'); + menuToggle.classList.remove('active'); + sidebarOverlay.classList.add('hidden'); + document.body.style.overflow = ''; +} + +menuToggle.addEventListener('click', toggleMobileMenu); +sidebarOverlay.addEventListener('click', closeMobileMenu); + async function initializeApp() { const hasSession = await checkSession(); diff --git a/frontend/src/style.css b/frontend/src/style.css index f34da31..048ad46 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -1043,4 +1043,146 @@ textarea:focus { .logout-btn:hover { color: var(--primary); +} + +/* Mobile Menu Toggle */ +.menu-toggle { + display: none; + position: fixed; + top: 16px; + right: 16px; + z-index: 1100; + background: var(--primary); + border: none; + width: 44px; + height: 44px; + border-radius: 10px; + cursor: pointer; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 5px; + box-shadow: 0 4px 15px var(--primary-glow); + transition: var(--transition); +} + +.menu-toggle .bar { + display: block; + width: 20px; + height: 2px; + background: white; + border-radius: 2px; + transition: var(--transition); +} + +.menu-toggle.active .bar:nth-child(1) { + transform: translateY(7px) rotate(45deg); +} + +.menu-toggle.active .bar:nth-child(2) { + opacity: 0; +} + +.menu-toggle.active .bar:nth-child(3) { + transform: translateY(-7px) rotate(-45deg); +} + +.sidebar-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(4px); + z-index: 1000; + transition: opacity 0.3s ease; +} + +/* Responsive Styles */ +@media (max-width: 768px) { + .menu-toggle { + display: flex; + } + + .sidebar { + position: fixed; + left: -320px; + top: 0; + height: 100%; + z-index: 1050; + transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1); + box-shadow: 10px 0 30px rgba(0, 0, 0, 0.5); + } + + .sidebar.open { + left: 0; + } + + .dashboard-view, .task-view { + padding: 20px; + padding-top: 80px; /* Space for menu button */ + height: auto; + min-height: 100%; + overflow-y: auto; + } + + .dashboard-header h2 { + font-size: 24px; + } + + .task-content { + flex-direction: column; + height: auto; + overflow: visible; + } + + .run-history { + width: 100%; + max-height: 200px; + flex-shrink: 0; + } + + .run-details { + flex-direction: column; + height: auto; + overflow: visible; + gap: 16px; + } + + .logs-container { + width: 100%; + height: 400px; + flex-shrink: 0; + } + + .view-header { + flex-direction: column; + align-items: flex-start; + gap: 16px; + } + + .header-actions { + width: 100%; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; + } + + .header-actions .btn { + justify-content: center; + } + + .modal { + width: 95%; + padding: 20px; + } + + .preset-group { + grid-template-columns: 1fr; + } + + .chat-container { + height: 500px; + } } \ No newline at end of file