diff --git a/web/app.js b/web/app.js index a34351d..be5246c 100644 --- a/web/app.js +++ b/web/app.js @@ -694,16 +694,21 @@ pane.classList.add('visible'); + const mobileBar = `
`; + if (state.peekMode === 'edit') { - pane.innerHTML = renderEditMode(e); + pane.innerHTML = mobileBar + renderEditMode(e); } else if (state.view === 'stream' || !e.card_type) { - pane.innerHTML = renderStreamPeek(e); + pane.innerHTML = mobileBar + renderStreamPeek(e); } else if (state.peekMode === 'run') { - pane.innerHTML = renderRunMode(e); + pane.innerHTML = mobileBar + renderRunMode(e); } else if (state.peekMode === 'fill') { - pane.innerHTML = renderFillMode(e); + pane.innerHTML = mobileBar + renderFillMode(e); } else { - pane.innerHTML = renderCardPeek(e); + pane.innerHTML = mobileBar + renderCardPeek(e); } bindPeekEvents(e); @@ -1401,6 +1406,20 @@ if (idx >= 0) { state.selectedIndex = idx; renderEntityList(); renderDetailPane(); } showToast(e.pinned ? 'unpinned' : 'pinned'); }, + + togglePeekFull() { + const pane = $('#detail-pane'); + pane.classList.toggle('peek-full'); + const btn = pane.querySelector('.peek-mobile-btn'); + if (btn) btn.textContent = pane.classList.contains('peek-full') ? '↓' : '↑'; + }, + + dismissPeek() { + const pane = $('#detail-pane'); + pane.classList.remove('visible', 'peek-full'); + state.selectedIndex = -1; + renderEntityList(); + }, }; // ========== Promote modal ========== @@ -1451,12 +1470,18 @@ return; } - if (ev.key === 'Escape' && $('main').classList.contains('focus-peek')) { - exitFocusPeek(); - state.selectedIndex = -1; - renderEntityList(); - renderDetailPane(); - return; + if (ev.key === 'Escape') { + const pane = $('#detail-pane'); + if ($('main').classList.contains('focus-peek')) { + exitFocusPeek(); + } + if (pane.classList.contains('visible')) { + pane.classList.remove('visible', 'peek-full'); + state.selectedIndex = -1; + renderEntityList(); + renderDetailPane(); + return; + } } const sel = state.entities[state.selectedIndex]; @@ -1540,7 +1565,16 @@ localStorage.setItem('nib:' + cls, m.classList.contains(cls) ? '1' : ''); } + function isMobileBreakpoint() { + return window.matchMedia('(max-width: 900px)').matches; + } + function toggleZen() { + if (isMobileBreakpoint()) { + if (state.selectedIndex >= 0) nibApp.togglePeekFull(); + return; + } + const m = $('main'); if (m.classList.contains('focus-peek')) { diff --git a/web/style.css b/web/style.css index 2e3863a..fd71a34 100644 --- a/web/style.css +++ b/web/style.css @@ -785,6 +785,28 @@ main.focus-peek .resize-handle { visibility: hidden; } overflow: hidden; } +.peek-mobile-bar { + display: none; + justify-content: space-between; + padding: 6px 12px; + border-bottom: 1px solid var(--border); +} + +.peek-mobile-btn { + font-family: var(--mono); + font-size: 14px; + color: var(--muted); + background: none; + border: 1px solid var(--border); + border-radius: 4px; + width: 28px; + height: 28px; + cursor: pointer; + transition: color var(--t-fast), border-color var(--t-fast); +} + +.peek-mobile-btn:hover { color: var(--accent); border-color: var(--accent); } + .peek-scroll { flex: 1; overflow-y: auto; @@ -1443,8 +1465,17 @@ kbd { background: var(--raised); border: 1px solid var(--border); border-radius: /* ── RESPONSIVE ─────────────────────────────────────── */ @media (max-width: 900px) { - main { grid-template-columns: 1fr; } - #tag-rail { display: none; } + main, + main.hide-rail, + main.hide-peek, + main.hide-rail.hide-peek, + main.focus-peek { + grid-template-columns: 1fr !important; + transition: none !important; + } + #tag-rail { display: none !important; } + .resize-handle { display: none !important; } + #entity-panel { overflow: auto; } #detail-pane { position: fixed; inset: 0; @@ -1458,4 +1489,7 @@ kbd { background: var(--raised); border: 1px solid var(--border); border-radius: z-index: 50; } #detail-pane.visible { transform: translateY(0); } + #detail-pane.peek-full { height: 100vh; height: 100dvh; top: 0; } + .peek-mobile-bar { display: flex; } + main.focus-peek #entity-panel { display: block; overflow: auto; min-width: 0; } }