Fix mobile chat: sticky header, hide dock switch, dvh viewport, closed-state-wins#4
Open
aaronaccessvr wants to merge 1 commit into
Open
Fix mobile chat: sticky header, hide dock switch, dvh viewport, closed-state-wins#4aaronaccessvr wants to merge 1 commit into
aaronaccessvr wants to merge 1 commit into
Conversation
Three changes to the chat-iframe Vue components plus a defensive reorder in the widget controller, addressing what mobile users see when the chat panel takes the full viewport. ChatHeader: pinned with `sticky top-0 z-10` so the back-and-close chrome stays anchored even when 100vh ends up larger than the visible mobile viewport (iOS Safari's URL-bar collapse) and the iframe scrolls. The header was already `shrink-0` in a flex layout, which works on desktop but doesn't survive the visual-viewport quirk on mobile. Dock / undock buttons: gated with `hidden sm:block` so they only show on the sm breakpoint and up. The previous code referenced `$store.state.config.isMobile`, but that flag is never populated in the chat-iframe store (it's read from a PHP-side config object that has no device awareness), so the rounded-corner and visibility checks that depended on it were effectively constant. Tailwind responsive classes handle this without an out-of-band signal. Chat container: switched to `h-dvh` (dynamic viewport height) and moved the rounded/border/overflow chrome to `sm:` prefixes so it only applies on the popup-and-up sizes. `h-screen` (100vh) overflows the visible viewport on mobile browsers with a collapsing URL bar, which was the underlying cause of the header-scrolling-out-of-view bug. widget.js initClient: reordered so `persistedState.open === false` short-circuits before the docked check. dock() opens the panel as a side effect, so if a stale `docked: true` flag survived alongside `open: false` (a stale combination that has shown up on mobile, where storage quotas and incognito states make persistence flakier), the old order would override the user's explicit close. Closed-state-wins now. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Four small Vue/JS changes that together fix the chat panel's mobile experience.
Changes
ChatHeader.vue — sticky top. Adds
sticky top-0 z-10to the header so the back-and-close chrome stays anchored even when iOS Safari's collapsing URL bar lets the flex layout overflow the visible viewport. The header was previouslyshrink-0in a flex column, which works on desktop but doesn't survive the mobile visual-viewport quirk.ChatHeader.vue — hide dock buttons on mobile. Replaces a
$store.state.config.isMobilecheck (which was effectively dead — that flag isn't populated in the chat-iframe store) withhidden sm:blockTailwind responsive classes on both the dock and undock buttons. Docking the widget on mobile doesn't make sense (the chat already fills the viewport), so the controls are simply hidden below thesmbreakpoint.Chat.vue — h-dvh + responsive chrome. Switches the container height from
h-screen(100vh) toh-dvh(100dvh), and moves the rounded-border-overflow chrome tosm:prefixes so the popup chrome only applies on desktop sizes.h-screenwas the root cause of the header-scrolling-out-of-view bug — on iOS Safari, 100vh is larger than the visible viewport while the URL bar is shown, which pushes the flex layout below the fold.widget.js initClient — closed-state-wins. Reorders the persistence-restore checks so
persistedState.open === falseshort-circuits before the docked check.dock()opens the panel as a side effect, so a staledocked: trueflag persisting alongsideopen: false(a rare but observed combination on mobile, where storage quotas and incognito make persistence flakier) used to override the user's explicit close. Now the explicit close always wins.Consumed by
AccessVR/OrchestrateLaravelApp PR (fix/mobile-chat-experience) bumps the submodule to this PR's tip and rebuilds + republishes the widget bundle. Originating bug: AccessVR/OrchestrateLaravelApp#1492.
Test plan
🤖 Generated with Claude Code