feat: zen mode — auto-hide chrome during a running breathing session - #33
Draft
abiassi wants to merge 1 commit into
Draft
feat: zen mode — auto-hide chrome during a running breathing session#33abiassi wants to merge 1 commit into
abiassi wants to merge 1 commit into
Conversation
When a breathing session is running, fade out the interface chrome (header: language switcher, sign-up / account menu, settings gear) so only the orb and its breathing visuals remain. Any sign of intent — mouse move, pointer/scroll, key press, touch, or a deliberate device-motion jolt — brings the chrome back, and it auto-hides again after ~3.5s of stillness. Chrome is always shown when the session is paused/stopped, when the settings sheet is open, or when the account menu is open. Reuses the running-session signal that the existing (never-wired) `immersive` mechanism was built around, but makes zen the default in-session behavior and adds the reveal/auto-hide layer it was missing. Accessibility: fades via opacity + pointer-events (never display:none), so controls stay in the tab order; a keydown reveals before focus lands and onFocusCapture re-reveals, so keyboard users are never trapped. Respects prefers-reduced-motion by collapsing the fade to a near-instant transition. Claude-Session: https://claude.ai/code/session_01TqA4N19mpP7BsPxCQbMMH8
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Adds zen mode to the breathing experience. When a session is running, the interface chrome fades away so only the orb and its breathing visuals remain. The chrome comes back the moment the user shows intent, then quietly hides again after a few seconds of stillness.
Chrome that fades (all inside the
Resonanceheader): the language switcher (EN), Sign up / account menu, and the settings gear. The orb (<Visualizer>), its phase label (INHALE / HOLD / …), and the ambient particle background stay.Reveal / auto-hide behavior
mousemove,pointermove,pointerdown,wheel,keydown.touchstart, plus device motion: a deliberate jolt of the phone reveals the chrome (best-effort; see caveat).How it reuses / extends the existing immersive mechanism
The codebase already had an
immersive?: booleanprop onResonanceand abody[data-resonance-immersive]/--immersive-colorbackground-tint effect keyed off the running session — but it was never wired to any page and never hid chrome. Rather than add a parallel special case, zen mode builds on that same running-session signal and makes chrome-hiding the default in-session behavior, adding the reveal + inactivity-timer layer the original mechanism was missing. The existing background-tint effect is left intact.Accessibility
pointer-events, neverdisplay:none— controls stay in the tab order and reachable.keydown(including Tab) reveals the chrome before focus lands, andonFocusCaptureon the header re-reveals as a backstop.pointer-events: noneso it never intercepts clicks meant for the orb.prefers-reduced-motion: the ~1.1s calm fade collapses to a near-instant 200ms transition.Verification
Verified in a real browser (claude-in-chrome on mbp16, over Tailscale) on
/box-breathing-app:opacity: 0; pointer-events: none; screenshot confirmed orb-only ("HOLD" showing, EN/Sign up/gear gone).mousemovereturned the header toopacity: 1; pointer-events: auto.touchstartlikewise revealed.opacity: 0,data-zen-hidden="true").tsc --noEmitclean.next buildpasses (exit 0). No console errors.Taste-calls for review
/box-breathing-app, a marketing hero heading ("Box breathing app: free online 4-4-4-4 timer") sits over the canvas as a sibling of<Resonance>, outside the component. Zen mode fades only the in-session chrome the request enumerated (header/controls), not that page-level copy. Fading it too would make a more complete "orb-only" moment but means touching ~10 landing pages with differing hero markup (all-or-nothing to stay consistent). Flagging as a follow-up rather than guessing — happy to do it if wanted.devicemotionbehind an explicit permission prompt. I deliberately do not trigger that prompt (intrusive during a calming session), so on iOS the reveal relies on touch/tap; motion-reveal works on Android/desktop sensors. The MCP browser viewport was locked at desktop width, so the touch/motion paths were verified via dispatched DOM events rather than a true mobile screenshot.https://claude.ai/code/session_01TqA4N19mpP7BsPxCQbMMH8