summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-26 01:36:27 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-26 01:36:27 +0200
commitbadbdd2635e62637fc03003e3115fd5b2391dba2 (patch)
tree7566a85720d628072a58939b9377013c4d07f96f
parent52707f6280bb268102cd60e692c0199a45caf35e (diff)
downloadmeshbay-badbdd2635e62637fc03003e3115fd5b2391dba2.tar.gz
fix(hub): stop hover/focus states from sticking on mobile touch
A tap on a touchscreen fires a synthetic hover with no "pointer left" to end it, and leaves the tapped element genuinely focused (unlike a desktop click) — so any :hover-styled button looked permanently "pressed" until something else was tapped, and any plain <button> with no custom hover at all (the nav hamburger) showed the browser's default focus ring for the same reason. Not reproducible on desktop, which actually has a mouse to move away with. Found live on mobile Chrome, 2026-08-26 — most visible on the music player's next/prev/shuffle buttons, but the same mechanism affects any button in the app. Two small, general fixes rather than a per-button patch: - `:focus:not(:focus-visible) { outline: none; }` in the global reset — clears a lingering focus ring from a pointer/touch interaction while leaving real keyboard-navigation focus untouched. - `.music-player-btn`/`.music-player-play`'s :hover rules scoped inside `@media (hover: hover)`, so a touch tap never triggers them at all. Only the two reported, confirmed cases are touched here — the same `@media (hover: hover)` wrap applies to any of the stylesheet's other :hover rules if the same stickiness shows up elsewhere. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013XSohfUQQiaE77qyFLgSv3
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/style.css24
1 files changed, 22 insertions, 2 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/style.css b/packages/meshbay-hub/src/meshbay_hub/static/style.css
index 9a4fb5a..5748b2d 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/style.css
+++ b/packages/meshbay-hub/src/meshbay_hub/static/style.css
@@ -48,6 +48,16 @@
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
+/* A tapped button keeps real DOM focus on mobile Chrome/Safari the way a
+ click never does on desktop — there's no mouse to move away afterward, so
+ the browser's own default focus ring (never reset anywhere in this file)
+ is what stayed visibly "pressed" until something else was tapped (found
+ live, 2026-08-26 — the nav hamburger has no :hover rule of its own at all,
+ so the ring was the only thing that could have been showing). `:focus-
+ visible` still shows it for real keyboard navigation — this only clears
+ the leftover from a pointer/touch interaction, never accessibility. */
+:focus:not(:focus-visible) { outline: none; }
+
body {
font-family: system-ui, -apple-system, sans-serif;
background: var(--bg-base);
@@ -3055,7 +3065,15 @@ a.transfer-name {
cursor: pointer;
position: relative;
}
-.music-player-btn:hover { background: var(--bg-surface); color: var(--text); }
+/* (hover: hover) — a tap on a touchscreen fires a synthetic hover that
+ never gets a "pointer left" to end it, so next/prev/shuffle stayed
+ highlighted as if still being pressed until some other element was
+ tapped (found live on mobile Chrome, 2026-08-26; not reproducible on
+ desktop, which actually has a mouse to move away with). Scoped to
+ devices that can genuinely hover — real hover behaviour is unaffected. */
+@media (hover: hover) {
+ .music-player-btn:hover { background: var(--bg-surface); color: var(--text); }
+}
.music-player-btn.active { color: var(--accent); }
.music-player-btn .icon { width: 16px; height: 16px; }
.music-player-play {
@@ -3064,7 +3082,9 @@ a.transfer-name {
background: var(--accent);
color: var(--accent-text);
}
-.music-player-play:hover { background: var(--accent-hover); color: var(--accent-text); }
+@media (hover: hover) {
+ .music-player-play:hover { background: var(--accent-hover); color: var(--accent-text); }
+}
.music-player-play:disabled { opacity: 0.6; cursor: not-allowed; }
.music-repeat-badge {
position: absolute;