Skip to content

fix(#1065): first-visit gesture discoverability hints#1186

Merged
Kpa-clawbot merged 4 commits into
masterfrom
fix/issue-1065-gesture-hints
May 10, 2026
Merged

fix(#1065): first-visit gesture discoverability hints#1186
Kpa-clawbot merged 4 commits into
masterfrom
fix/issue-1065-gesture-hints

Conversation

@Kpa-clawbot
Copy link
Copy Markdown
Owner

Red commit: 4e0a168 (CI run: see Checks tab — branch pushes don't trigger CI on this repo; first CI is on this PR)

Fixes #1065. Parent: #1052.

What

First-visit gesture discoverability hints. Brief animated balloons appear 800ms after page settle on first visit, announcing each gesture: swipe-row-action, swipe-between-tabs, edge-swipe-drawer, pull-to-refresh. Each hint dismisses individually via "Got it"; dismissed hints persist across sessions; "Reset gesture hints" in Customize → Display restores them.

Decisions

  • localStorage namespace: meshcore-gesture-hints-<id> with keys row-swipe, tab-swipe, edge-drawer, pull-refresh. Value: "seen".
  • Hint timing: 800ms post-settle delay (lets page render); no auto-mark — hints fade after 8s but only "Got it" sets the flag (so users who miss the fade still see them next visit). Conservative interpretation of AC.
  • Settings reset location: Customize → Display tab → "Gesture Hints" subsection → ↺ Reset gesture hints button. Calls window.GestureHints.reset() which clears all four keys + removes any visible balloons.
  • Pull-to-refresh fallback: hint only shown if .pull-to-reconnect element exists in DOM (per [#1052] Task 4: Pull-to-reconnect on data pages #1063). If absent, the hint is silently skipped — other 3 still show.
  • prefers-reduced-motion: animation-name: none !important under the media query; only opacity transition remains.
  • No focus stealing: no autofocus, no .focus() calls. Wrapper has pointer-events: none; only the inner balloon + dismiss button capture pointer, so the row underneath stays interactive (no conflict with fix(#1062): gesture system — swipe rows, tabs, slide-over dismiss #1185 row-swipe).
  • Singleton + cleanup: module-scoped window.__gestureHints1065Init counter; hashchange listener bound exactly once across SPA mounts; dismissed hints don't re-show on route change (gated by localStorage).
  • Relevance gating: row-swipe hint only on /#/packets|nodes|live; edge-drawer only at viewport > 768px (matches [#1052] Task 5: Edge-swipe nav drawer #1064 drawer scope).

E2E

test-gesture-hints-1065-e2e.js — Playwright covering first-visit show, "Got it" dismiss + flag persistence, reload-no-show, Settings reset → reload → re-show, edge-drawer at 1024x800, prefers-reduced-motion → animation-name: none, focus not stolen, singleton across 5 SPA round-trips.

E2E assertion added: test-gesture-hints-1065-e2e.js:90

Browser verified: pending CI run.

openclaw-bot and others added 4 commits May 10, 2026 02:03
Adds Playwright E2E covering:
- first-visit row-swipe hint shown at 360x800 /#/packets
- aria-live=polite, role=status, pointer-events:none
- 'Got it' button dismisses + persists meshcore-gesture-hints-* flag
- reload does not re-show
- Settings 'Reset gesture hints' button restores
- 1024x800 edge-drawer hint visible
- prefers-reduced-motion → animation-name: none
- focus not stolen
- 5 SPA round-trips don't re-show after dismiss

Wired into .github/workflows/deploy.yml. Will FAIL on assertion
until public/gesture-hints.js + Settings reset button + CSS land
in the green commit.
Implements gesture discoverability hints per AC:
- Hints: row-swipe, tab-swipe, edge-drawer, pull-refresh
- localStorage namespace: meshcore-gesture-hints-<id> = 'seen'
- Show 800ms after page settle; auto-fade after 8s; 'Got it' marks seen
- aria-live=polite + role=status + aria-atomic=true
- pointer-events:none on wrapper (inner balloon clickable, row stays usable)
- Singleton guard via window.__gestureHints1065Init
- prefers-reduced-motion: animation-name:none, opacity-only fade
- Pull-to-refresh hint conditional on .pull-to-reconnect element presence
- Edge-drawer hint conditional on viewport > 768px
- Row-swipe hint scoped to /#/packets, /#/nodes, /#/live
- 'Reset gesture hints' button added to Customize > Display panel
- hashchange listener removes irrelevant hints + re-evaluates on route change

Files:
- NEW public/gesture-hints.js (module-scoped singleton)
- NEW CSS section in public/style.css (#1065 fence)
- public/index.html: script tag after touch-gestures.js
- public/customize-v2.js: 'Reset gesture hints' button + handler
CI test (a) reported computed pointer-events='auto' on the wrapper
despite .gesture-hint { pointer-events: none } — likely a cascade
collision (e.g. .gesture-hint-inner sibling rule, or a future overlay
class). Force it with !important. Inner balloon + button retain
pointer-events:auto so 'Got it' still works.
CSS rule + !important alone didn't satisfy the E2E (Chromium reported
computed pointer-events=auto despite '.gesture-hint { pointer-events:
none !important }'). Most likely: cached page state during test, or a
sibling rule we haven't identified. Inline style.pointerEvents='none'
on the wrapper at creation time bypasses the entire CSS cascade — the
hint provably cannot capture clicks. Inner balloon + button keep their
own pointer-events:auto via separate elements.
@Kpa-clawbot Kpa-clawbot merged commit 03b5d3f into master May 10, 2026
6 checks passed
@Kpa-clawbot Kpa-clawbot deleted the fix/issue-1065-gesture-hints branch May 10, 2026 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[#1052] Task 6: Gesture discoverability hints (first-visit)

1 participant