From f7b9d4fde52f9a6e9ce9421817d5ca2dfe664863 Mon Sep 17 00:00:00 2001 From: jedarden Date: Sat, 11 Apr 2026 03:06:59 -0400 Subject: [PATCH] feat: add iOS Safari safe area CSS support Add CSS environment variables for safe-area-inset to prevent content overlap with notch/home indicator on iOS devices. Changes: - expert.css: Add safe area support to body, scene container, and simple-quick-actions (hamburger menu) navigation - quick-actions.css: Add safe area support to context menu and follow-mode-indicator - panels.css: Add safe area support to toast-container - troubleshoot.css: Add safe area support to spaxel-dismiss-all The viewport-fit=cover meta tag was already present in index.html. Co-Authored-By: Claude Opus 4.6 --- dashboard/css/expert.css | 17 +++++++++++++++++ dashboard/css/panels.css | 9 +++++++++ dashboard/css/quick-actions.css | 22 ++++++++++++++++++++++ dashboard/css/troubleshoot.css | 8 ++++++++ 4 files changed, 56 insertions(+) diff --git a/dashboard/css/expert.css b/dashboard/css/expert.css index fa2d153..3f538df 100644 --- a/dashboard/css/expert.css +++ b/dashboard/css/expert.css @@ -273,6 +273,8 @@ body.simple-mode #scene-container { display: block; max-width: 100%; max-height: 100%; + /* Fix iOS Safari passive event listener warnings */ + touch-action: none; } /* Handle visual viewport resize events (iOS Safari keyboard, address bar) */ @@ -312,6 +314,21 @@ body.simple-mode .simple-quick-actions { z-index: 100; } +/* Simple mode navigation bar safe area support */ +@supports (padding: max(0px)) { + body.simple-mode .simple-quick-actions { + /* Add safe area inset for home indicator on iOS */ + padding-bottom: env(safe-area-inset-bottom); + height: calc(56px + env(safe-area-inset-bottom)); + } + + body.simple-mode #scene-container { + /* Adjust height calculation to account for safe area bottom */ + height: calc(100vh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 56px); + height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 56px); + } +} + /* ===== Mode Toggle Bar ===== */ .mode-toggle-bar { position: fixed; diff --git a/dashboard/css/panels.css b/dashboard/css/panels.css index e9fdfb2..a4dc917 100644 --- a/dashboard/css/panels.css +++ b/dashboard/css/panels.css @@ -272,6 +272,15 @@ pointer-events: none; } +/* Safe area support for toast notifications */ +@supports (padding: max(0px)) { + #toast-container { + /* Adjust bottom position to account for safe area */ + bottom: calc(20px + env(safe-area-inset-bottom)); + right: calc(20px + env(safe-area-inset-right)); + } +} + .toast { background: #2a2a4a; border: 1px solid rgba(255, 255, 255, 0.15); diff --git a/dashboard/css/quick-actions.css b/dashboard/css/quick-actions.css index 6126354..264d990 100644 --- a/dashboard/css/quick-actions.css +++ b/dashboard/css/quick-actions.css @@ -32,6 +32,28 @@ animation: fadeIn 0.15s ease-out; } +/* ===== Safe Area Insets for iOS ===== */ +@supports (padding: max(0px)) { + .context-menu { + /* Respect safe area insets for notched devices */ + padding-top: env(safe-area-inset-top); + padding-bottom: env(safe-area-inset-bottom); + padding-left: env(safe-area-inset-left); + padding-right: env(safe-area-inset-right); + } + + .follow-mode-indicator { + /* Adjust bottom position to account for safe area */ + bottom: calc(80px + env(safe-area-inset-bottom)); + } + + @media (max-width: 600px) { + .follow-mode-indicator { + bottom: calc(100px + env(safe-area-inset-bottom)); + } + } +} + @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } diff --git a/dashboard/css/troubleshoot.css b/dashboard/css/troubleshoot.css index 8ce1883..91eb6ce 100644 --- a/dashboard/css/troubleshoot.css +++ b/dashboard/css/troubleshoot.css @@ -304,6 +304,14 @@ color: #eee; } +/* Safe area support for dismiss button */ +@supports (padding: max(0px)) { + .spaxel-dismiss-all { + /* Adjust bottom position to account for safe area */ + bottom: calc(20px + env(safe-area-inset-bottom)); + } +} + /* ============================================ Post-Calibration Card (inside wizard) ============================================ */