From 7ad9707c4b5b6be4e3f55d64398a68afed3a5fe2 Mon Sep 17 00:00:00 2001 From: nesquena-hermes Date: Sun, 5 Jul 2026 06:40:26 +0000 Subject: [PATCH] fix(ui): align mobile sidebar close (X) with the new-conversation (+) button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On the mobile sidebar header the close (X) button rendered an 18px glyph — the only 18px .panel-head-btn icon — sitting ~6px lower than the adjacent 14px new-conversation (+) button, an inconsistent pair. Match the X glyph to 14px and vertically center it on the ~41px panel-head row so both icons share one size and baseline (top:calc(safe-top - 2px) keeps the existing safe-area offset so the X still clears the notch, with no extra drawer spacing). 44x44 tap target kept for mobile touch; mobile @media(max-width:640px) only, and the X is display:none on desktop, so desktop is unaffected. + CHANGELOG + source-guard tests. --- CHANGELOG.md | 1 + static/style.css | 11 ++++-- .../test_mobile_sidebar_header_icon_align.py | 35 +++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 tests/test_mobile_sidebar_header_icon_align.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 30df1ad5..a91f00a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ ### Fixed +- **Mobile sidebar header: the close (✕) and new-conversation (+) buttons are now a consistent, aligned pair.** The close button rendered a larger icon sitting slightly lower than the adjacent + button; both now use the same icon size on the same baseline, with the tap target kept large enough for comfortable mobile use. Desktop is unaffected. (mobile UI polish) - **iOS PWA: tapping a conversation now closes the sidebar immediately and reliably opens it.** On the mobile PWA, tapping an older (large) conversation left the sidebar drawer open for several seconds with only a tiny spinner — and a background refresh could cancel the switch mid-flight so the conversation never opened and the highlight jumped back. The sidebar now closes the instant you tap (matching how ChatGPT/Claude mobile dismiss the drawer on select, with a "Loading conversation…" placeholder in the chat area), and an in-flight session switch is protected from being cancelled by a concurrent background refresh. Desktop is unaffected. Thanks @luperrypf. (#5602) - **OpenCode Go: the model picker no longer lists models that 404 when you send.** OpenCode Go's live model probe returned entries from the full public catalog that aren't enabled on the Go tier, so picking one failed with "model not found" on the first message. The picker now uses the curated Go-tier model list for this provider instead of the live probe. Thanks @webtecnica. (#5611, #5311) - **The sidebar's "Retry" button now gives feedback when a conversation-list load fails.** When the session list failed to load, its Retry button behaved like an inert browser default — clicking it gave no sign anything happened while the (often slow) refetch ran, so it looked broken. Retry now shows an immediate "Retrying…" pending state, restores to "Retry" if it fails again, and is properly styled to match the sidebar. It's also accessible (the error is a polite live region; the pending button keeps keyboard focus) and can't get stuck pending if you switch profiles mid-retry. Thanks @rodboev. (#5505, #5501) diff --git a/static/style.css b/static/style.css index 7b13fe22..c0dccfe9 100644 --- a/static/style.css +++ b/static/style.css @@ -3151,8 +3151,15 @@ } @media (max-width: 640px){ - .panel-head-btn.mobile-sidebar-close{display:inline-flex!important;right:4px;top:calc(4px + var(--app-titlebar-safe-top));width:44px!important;height:44px!important;min-width:44px;min-height:44px;line-height:1;overflow:hidden;} - .panel-head-btn.mobile-sidebar-close svg{width:18px;height:18px;display:block;} + /* Match the close (X) glyph to the new-conversation (+) button's 14px size + (previously 18px — the only 18px panel-head icon, so the X read visibly + larger than the +) and align its vertical center with the +. The + sits + centered in the 41px panel-head row (center ~20px from the header top); the + X is a 44px box, so top:calc(safe-top - 2px) centers it on the same row + ((41-44)/2 ≈ -2) while keeping the existing safe-area offset so it still + clears the notch. No extra drawer spacing. 44x44 tap target kept for touch. */ + .panel-head-btn.mobile-sidebar-close{display:inline-flex!important;align-items:center;justify-content:center;right:4px;top:calc(var(--app-titlebar-safe-top) - 2px);width:44px!important;height:44px!important;min-width:44px;min-height:44px;line-height:1;overflow:hidden;} + .panel-head-btn.mobile-sidebar-close svg{width:14px;height:14px;display:block;} /* Keep mobile send-button reveal motion off: avoids 0.18s pop-in in tight composer layouts, which can jitter the 44px hit area while typing/scrolling. */ .send-btn.visible{animation:none;opacity:1;transform:none;} diff --git a/tests/test_mobile_sidebar_header_icon_align.py b/tests/test_mobile_sidebar_header_icon_align.py new file mode 100644 index 00000000..1f699770 --- /dev/null +++ b/tests/test_mobile_sidebar_header_icon_align.py @@ -0,0 +1,35 @@ +"""Mobile sidebar header: the close (X) button must visually match the +new-conversation (+) button — same 14px glyph, vertically aligned on the +panel-head row — instead of a larger 18px glyph sitting ~6px lower. Source guard. +Mobile-only (@media max-width:640px); desktop hides the X entirely. +""" + +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +STYLE = (ROOT / "static" / "style.css").read_text(encoding="utf-8") + + +def test_mobile_close_glyph_matches_plus_button_size(): + # + button glyph is 14px (.panel-head-btn svg{width:14px}); the mobile X must match. + assert ".panel-head-btn svg{width:14px;height:14px" in STYLE + assert ".panel-head-btn.mobile-sidebar-close svg{width:14px;height:14px" in STYLE + # The old oversized 18px glyph must be gone. + assert ".panel-head-btn.mobile-sidebar-close svg{width:18px" not in STYLE + + +def test_mobile_close_is_centered_and_keeps_tap_target(): + close_rule = STYLE[STYLE.index(".panel-head-btn.mobile-sidebar-close{"):] + close_rule = close_rule[: close_rule.index("}") + 1] + # Glyph centered in the button. + assert "align-items:center" in close_rule and "justify-content:center" in close_rule + # 44x44 tap target preserved for mobile touch. + assert "width:44px!important;height:44px!important" in close_rule + # Keeps the safe-area offset (so it still clears the notch) — no extra blank + # drawer padding. + assert "var(--app-titlebar-safe-top)" in close_rule + + +def test_mobile_close_hidden_on_desktop(): + # Base (non-media) rule hides the X on desktop — this fix is mobile-only. + assert ".mobile-sidebar-close{display:none;}" in STYLE