Spaces:
Running on Zero
Mobile UI: bound the autocomplete dropdown + denser drawer + keyboard handling
Browse filesThe "typing narrows the menu" issue: the start/destination autocomplete list
had max-height:none, so a 9-item dropdown grew unbounded and buried the rest of
the menu (Destination/Mode/sliders), with its tail clipped by the CTA. Cap it at
min(46vh,300px) with internal scroll so it stays compact.
Also for mobile readability:
- Tighten drawer density (panel padding, control margins, chip gap) so more of
the menu is visible at once — the brand + vibe header no longer clip at the top.
- Add a visualViewport handler: when the on-screen keyboard opens, size the
bottom drawer to the visible area above it and scroll the focused field into
view (dvh alone gets crushed on Android / overlaid on iOS).
Verified in the mobile preview (375px): dropdown now 300px + scrollable; full
menu (vibe → Plan button) scrolls cleanly; no console errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@@ -88,7 +88,9 @@ body{ font-family:'DM Sans',ui-sans-serif,system-ui,sans-serif; color:var(--dr-i
|
|
| 88 |
.combo{ position:relative; }
|
| 89 |
.combo-list{ position:absolute; z-index:60; left:0; right:0; top:calc(100% + 5px);
|
| 90 |
background:var(--dr-paper); border:1.5px solid var(--dr-line); border-radius:16px;
|
| 91 |
-
box-shadow:0 18px 38px -16px rgba(43,38,32,.45);
|
|
|
|
|
|
|
| 92 |
.combo-list.open{ display:block; animation:drPop .16s var(--dr-spring); }
|
| 93 |
@keyframes drPop{ from{ transform:translateY(-4px); opacity:.4; } to{ transform:none; opacity:1; } }
|
| 94 |
.combo-list div{ padding:9px 11px; font-size:13.5px; cursor:pointer; border-radius:11px;
|
|
@@ -270,6 +272,11 @@ details.dr-collapse .collapse-body{ padding:13px 15px; }
|
|
| 270 |
transform:translateY(110%); transition:transform .32s var(--dr-spring);
|
| 271 |
padding-top:8px; }
|
| 272 |
.left-panel.open{ transform:translateY(0); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 273 |
.fab{ display:grid; place-items:center; position:fixed; right:18px; bottom:18px; z-index:210;
|
| 274 |
width:62px; height:62px; border-radius:50%; border:none; cursor:pointer;
|
| 275 |
background:var(--dr-coral); color:#fff; font-size:15px; font-family:'Fredoka',sans-serif;
|
|
@@ -804,6 +811,35 @@ const closeDrawer = () => $("left-panel").classList.remove("open");
|
|
| 804 |
$("fab").addEventListener("click", openDrawer);
|
| 805 |
$("drawer-close").addEventListener("click", closeDrawer);
|
| 806 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 807 |
/* ---------- floating results sheet (collapsible overlay) ---------- */
|
| 808 |
function showSheet() { const s = $("results-sheet"); if (s) { s.hidden = false; s.classList.remove("collapsed"); } }
|
| 809 |
function hideSheet() { const s = $("results-sheet"); if (s) s.hidden = true; }
|
|
|
|
| 88 |
.combo{ position:relative; }
|
| 89 |
.combo-list{ position:absolute; z-index:60; left:0; right:0; top:calc(100% + 5px);
|
| 90 |
background:var(--dr-paper); border:1.5px solid var(--dr-line); border-radius:16px;
|
| 91 |
+
box-shadow:0 18px 38px -16px rgba(43,38,32,.45); display:none; padding:5px;
|
| 92 |
+
max-height:min(46vh,300px); overflow-y:auto; overflow-x:hidden;
|
| 93 |
+
overscroll-behavior:contain; }
|
| 94 |
.combo-list.open{ display:block; animation:drPop .16s var(--dr-spring); }
|
| 95 |
@keyframes drPop{ from{ transform:translateY(-4px); opacity:.4; } to{ transform:none; opacity:1; } }
|
| 96 |
.combo-list div{ padding:9px 11px; font-size:13.5px; cursor:pointer; border-radius:11px;
|
|
|
|
| 272 |
transform:translateY(110%); transition:transform .32s var(--dr-spring);
|
| 273 |
padding-top:8px; }
|
| 274 |
.left-panel.open{ transform:translateY(0); }
|
| 275 |
+
/* denser drawer so more of the menu is visible in the cramped mobile height */
|
| 276 |
+
.panel-scroll{ padding:12px 16px 8px; }
|
| 277 |
+
.dr-control{ margin-bottom:12px; }
|
| 278 |
+
.brand{ margin-bottom:10px; }
|
| 279 |
+
.vibe-chips{ gap:7px; }
|
| 280 |
.fab{ display:grid; place-items:center; position:fixed; right:18px; bottom:18px; z-index:210;
|
| 281 |
width:62px; height:62px; border-radius:50%; border:none; cursor:pointer;
|
| 282 |
background:var(--dr-coral); color:#fff; font-size:15px; font-family:'Fredoka',sans-serif;
|
|
|
|
| 811 |
$("fab").addEventListener("click", openDrawer);
|
| 812 |
$("drawer-close").addEventListener("click", closeDrawer);
|
| 813 |
|
| 814 |
+
/* Keep the bottom drawer usable when the on-screen keyboard opens. On phones the
|
| 815 |
+
keyboard shrinks the *visual* viewport (and on iOS overlays a fixed element)
|
| 816 |
+
so a dvh-sized drawer gets crushed or hidden. We size the drawer to the
|
| 817 |
+
visible area above the keyboard and scroll the focused field into view. */
|
| 818 |
+
(function () {
|
| 819 |
+
const vv = window.visualViewport;
|
| 820 |
+
if (!vv) return;
|
| 821 |
+
const panel = $("left-panel");
|
| 822 |
+
const fit = () => {
|
| 823 |
+
if (window.innerWidth > 768 || !panel.classList.contains("open")) {
|
| 824 |
+
panel.style.maxHeight = ""; return; // desktop / closed: CSS rules
|
| 825 |
+
}
|
| 826 |
+
panel.style.maxHeight = Math.round(vv.height * 0.94) + "px";
|
| 827 |
+
};
|
| 828 |
+
vv.addEventListener("resize", fit);
|
| 829 |
+
vv.addEventListener("scroll", fit);
|
| 830 |
+
document.addEventListener("focusin", (e) => {
|
| 831 |
+
if (window.innerWidth > 768) return;
|
| 832 |
+
const field = e.target.closest && e.target.closest(".left-panel input, .left-panel textarea");
|
| 833 |
+
if (!field) return;
|
| 834 |
+
openDrawer(); fit();
|
| 835 |
+
// let the keyboard animate in, then center the field within the scroll area
|
| 836 |
+
setTimeout(() => field.scrollIntoView({ block: "center", behavior: "smooth" }), 280);
|
| 837 |
+
});
|
| 838 |
+
document.addEventListener("focusout", () => {
|
| 839 |
+
if (window.innerWidth <= 768) setTimeout(fit, 100);
|
| 840 |
+
});
|
| 841 |
+
})();
|
| 842 |
+
|
| 843 |
/* ---------- floating results sheet (collapsible overlay) ---------- */
|
| 844 |
function showSheet() { const s = $("results-sheet"); if (s) { s.hidden = false; s.classList.remove("collapsed"); } }
|
| 845 |
function hideSheet() { const s = $("results-sheet"); if (s) s.hidden = true; }
|