Files
eveAI/documentation/mobile-ux.md
Josako 16ce59ae98 - Introduce cache busting (to circumvent aggressive caching on iOS - but ideal in other contexts as well)
- Change the build process to allow cache busting
- Optimisations to the build process
- Several improvements of UI geared towards mobile experience
-
2025-09-25 17:28:01 +02:00

6.4 KiB
Raw Blame History

Mobile UX Improvements for EveAI Chat Client

This document explains the changes we made to improve the mobile user experience and how to verify or tweak them.

Summary of Issues Addressed

  • Unwanted white margins and page scroll on mobile due to default body margin and mixed vh/dvh usage.
  • Layout jitter and incorrect heights when the browser address bar or the on-screen keyboard appears.
  • Chat input potentially being obscured by the keyboard.
  • Differences between DevTools emulation and real devices.

Key Changes

  1. CSS base reset and layout fixes
  • Remove default white margins and prevent double scroll.
  • Ensure outer containers dont create conflicting scrollbars.
  • Respect device safe-area insets (bottom notch, etc.).

Files:

  • eveai_chat_client/templates/base.html
    • Added a CSS custom property fallback: --vvh: 1vh; on :root.
  • eveai_chat_client/static/assets/css/chat.css
    • .app-container now uses height: calc(var(--vvh, 1vh) * 100);.
    • Added base reset: body { margin: 0; overflow: hidden; } and global box-sizing: border-box.
    • Mobile .content-area no longer uses calc(100vh - header); we rely on flex with min-height: 0.
  • eveai_chat_client/static/assets/css/chat-components.css
    • Added padding-bottom: env(safe-area-inset-bottom) for the chat input area on mobile.
    • When keyboard is open (detected via JS), we slightly increase bottom padding.
  1. VisualViewport utility and debug overlay
  • We introduced a small utility that:
    • Sets a CSS variable --vvh equal to 1% of the current visual viewport height.
    • Toggles a keyboard-open class on <body> when the keyboard is likely visible.
    • Optionally shows a debug overlay with real-time viewport metrics.

Files:

  • frontend_src/js/utils/viewport.js (new)
    • Exports initViewportFix({ enableDebug }).
    • Updates --vvh on resize/scroll/orientation changes.
    • Optional debug overlay via enableDebug.
  • frontend_src/js/chat-client.js
    • Imports and initializes the util on DOMContentLoaded.
    • Enable overlay via query parameter: ?debug=viewport.

How It Works

  • CSS reads --vvh to size the vertical layout. This follows the visual viewport, so when the URL bar or keyboard affects the viewport, the chat layout adapts without extra page scroll.
  • The keyboard-open body class allows us to slightly increase bottom padding for the input to avoid edge cases where the input is near the keyboard.
  • On mobile, .app-container spans the full visual viewport height, and .content-area flexes to take remaining space under the mobile header without relying on height calculations.

Testing Checklist

  1. Open the chat on real devices (iOS Safari, Android Chrome).
  2. Verify there are no white margins around the app; the overall page should not scroll.
  3. Focus the message input:
    • Keyboard appears; the message list should stay usable and the input should remain visible.
    • The page should not jump in height unexpectedly.
  4. Rotate device (portrait/landscape) and ensure the layout adapts.
  5. Try with/without the browser UI (scroll a bit to collapse the address bar on Android Chrome).
  6. Optional: enable overlay with ?debug=viewport and verify reported values look sane.

Tuning and Fallbacks

  • If you need to support extremely old iOS versions that lack VisualViewport, we still fall back to 1vh for --vvh. You can increase robustness by setting --vvh via a simple window.innerHeight measurement on load.
  • Keyboard detection is heuristic-based (drop > 120px). Adjust the threshold in viewport.js if needed for specific device groups.
  • Avoid adding fixed height: 100vh or calc(100vh - X) to new containers; prefer flex layouts with min-height: 0 for scrollable children.

Known Limitations

  • On some embedded browsers (in-app webviews), viewport behavior can deviate; test with your target apps.
  • The safe-area env variables require modern browsers; most iOS/Android are fine, but always test.

Enabling/Disabling Debug Overlay

  • Append ?debug=viewport to the URL to enable.
  • The overlay displays: innerHeight, clientHeight, visualViewport.height, visualViewport.pageTop, header height, current --vvh, and keyboard state.

Next Steps (Optional Enhancements)

  • PWA manifest with display: standalone to reduce address bar effects.
  • Add smooth scroll-into-view on input focus for edge cases on particular webviews.
  • Add E2E tests using BrowserStack for a small device matrix.

Focus Zoom Prevention (2025-09-24)

Some mobile browsers (notably iOS Safari) auto-zoom when focusing inputs with small font sizes. To prevent this:

  • We enforce font-size: 16px for inputs, selects, textareas, and buttons on mobile in chat-components.css.
  • We stabilize text scaling via -webkit-text-size-adjust: 100%.
  • We extended the meta viewport with viewport-fit=cover.
  • The debug overlay now also shows visualViewport.scale to confirm no zoom is happening (expect 1.00 during focus).

Files:

  • eveai_chat_client/static/assets/css/chat-components.css (mobile form control font-size)
  • eveai_chat_client/static/assets/css/chat.css (text-size-adjust)
  • eveai_chat_client/templates/base.html (viewport meta)
  • frontend_src/js/utils/viewport.js (overlay shows vv.scale)

Validation checklist:

  • Focus the chat input and language select on iOS Safari and Android Chrome; the UI should not scale up.
  • Overlay shows vv.scale: 1.00 with ?debug=viewport.

Mobile Header Overflow Fix (2025-09-24)

We observed that the mobile header could push the layout wider than the viewport on small devices, causing horizontal page scroll. We addressed this by:

  • Allowing the header row to wrap: .mobile-header { flex-wrap: wrap; }.
  • Ensuring children can shrink within the container: min-width: 0 on .mobile-logo and .mobile-language-selector.
  • Constraining controls: :deep(.language-select) uses max-width: 100% and on very small screens max-width: 60vw.
  • Preventing accidental bleed: .mobile-header { max-width: 100%; overflow: hidden; }.
  • Added html { overflow-x: hidden; } as a light global failsafe.

Files:

  • eveai_chat_client/static/assets/vue-components/MobileHeader.vue (scoped styles updated)
  • eveai_chat_client/static/assets/css/chat.css (added html { overflow-x: hidden; })

Validation checklist:

  • On 320px width devices, header may wrap to 2 lines without horizontal scroll.
  • Long tenant names and multiple languages do not cause page-wide overflow; content remains within viewport width.