jofaichow commited on
Commit
bb9def6
·
1 Parent(s): e65d7f0

Fix iPhone responsive layout: threshold, MutationObserver, map hiding

Browse files

- Changed stacking threshold from screen.width*0.50 to fixed 768px
breakpoint (old formula gave ~195px on iPhone — stacking never fired)
- Added MutationObserver to re-run stacking when Streamlit injects cards
and map via websocket after page load
- Map now hidden via inline JS style.setProperty in addition to CSS
- Card collapse retriggers on DOM mutations, not just window.load

Files changed (1) hide show
  1. src/styles/dark_theme.py +49 -6
src/styles/dark_theme.py CHANGED
@@ -834,22 +834,25 @@ FORCE_DARK_WRAPPER_JS = """<!DOCTYPE html>
834
  } catch(e) {
835
  /* Cross-origin iframe — can't access parent. This is expected. */
836
  }
837
- })();
838
  </script>"""
839
 
840
  STACK_CONTROLS_JS = """<!DOCTYPE html>
 
 
841
  <script>
842
  (function() {
843
  try {
844
  var p = window.parent;
845
  if (!p) return;
846
 
847
- var threshold = p.screen.width * 0.50;
 
848
 
849
  function updateStack() {
850
  var body = p.document.body;
851
  if (!body) return;
852
- var isNarrow = p.window.innerWidth <= threshold;
853
  body.classList.toggle('stack-columns', isNarrow);
854
 
855
  // Apply 4-row layout to search controls (first horizontal block) only
@@ -881,14 +884,41 @@ STACK_CONTROLS_JS = """<!DOCTYPE html>
881
  for (var i = 0; i < expanders.length; i++) {
882
  expanders[i].removeAttribute('open');
883
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
884
  }
885
  }
886
 
887
  // Run on load
888
  if (document.readyState === 'complete') {
889
- updateStack();
890
  } else {
891
- p.window.addEventListener('load', updateStack);
 
 
892
  }
893
 
894
  // Debounced resize
@@ -897,11 +927,24 @@ STACK_CONTROLS_JS = """<!DOCTYPE html>
897
  clearTimeout(timer);
898
  timer = setTimeout(updateStack, 100);
899
  });
 
 
 
 
 
 
 
 
 
 
 
900
  } catch(e) {
901
  /* Cross-origin — silently skip */
902
  }
903
  })();
904
- </script>"""
 
 
905
 
906
  def apply_dark_theme():
907
  """Inject dark-theme CSS, flexible panel JS, card↔map hover JS, and smart image positioning JS."""
 
834
  } catch(e) {
835
  /* Cross-origin iframe — can't access parent. This is expected. */
836
  }
837
+ })();
838
  </script>"""
839
 
840
  STACK_CONTROLS_JS = """<!DOCTYPE html>
841
+ <html>
842
+ <body>
843
  <script>
844
  (function() {
845
  try {
846
  var p = window.parent;
847
  if (!p) return;
848
 
849
+ // Fixed breakpoint matching CSS @media (max-width: 768px)
850
+ var BREAKPOINT = 768;
851
 
852
  function updateStack() {
853
  var body = p.document.body;
854
  if (!body) return;
855
+ var isNarrow = p.window.innerWidth <= BREAKPOINT;
856
  body.classList.toggle('stack-columns', isNarrow);
857
 
858
  // Apply 4-row layout to search controls (first horizontal block) only
 
884
  for (var i = 0; i < expanders.length; i++) {
885
  expanders[i].removeAttribute('open');
886
  }
887
+
888
+ // Hide the map container directly (more reliable than CSS alone)
889
+ var mapContainer = body.querySelector('.stCustomComponentV1');
890
+ if (mapContainer) {
891
+ mapContainer.style.setProperty('display', 'none', 'important');
892
+ }
893
+ // Hide the map title
894
+ var mapTitles = body.querySelectorAll('h3');
895
+ for (var i = 0; i < mapTitles.length; i++) {
896
+ if (mapTitles[i].textContent.trim() === '🗺️ Map') {
897
+ mapTitles[i].style.setProperty('display', 'none', 'important');
898
+ }
899
+ }
900
+ } else {
901
+ // Restore map visibility
902
+ var mapContainer = body.querySelector('.stCustomComponentV1');
903
+ if (mapContainer) {
904
+ mapContainer.style.display = '';
905
+ }
906
+ var mapTitles = body.querySelectorAll('h3');
907
+ for (var i = 0; i < mapTitles.length; i++) {
908
+ if (mapTitles[i].textContent.trim() === '🗺️ Map') {
909
+ mapTitles[i].style.display = '';
910
+ }
911
+ }
912
  }
913
  }
914
 
915
  // Run on load
916
  if (document.readyState === 'complete') {
917
+ setTimeout(updateStack, 100);
918
  } else {
919
+ p.window.addEventListener('load', function() {
920
+ setTimeout(updateStack, 100);
921
+ });
922
  }
923
 
924
  // Debounced resize
 
927
  clearTimeout(timer);
928
  timer = setTimeout(updateStack, 100);
929
  });
930
+
931
+ // Watch for DOM changes — Streamlit renders content via websocket
932
+ // after the page loads, so we need to re-run when cards/map appear
933
+ var moTimer;
934
+ var observer = new MutationObserver(function() {
935
+ clearTimeout(moTimer);
936
+ moTimer = setTimeout(updateStack, 200);
937
+ });
938
+ if (p.document.body) {
939
+ observer.observe(p.document.body, { childList: true, subtree: true });
940
+ }
941
  } catch(e) {
942
  /* Cross-origin — silently skip */
943
  }
944
  })();
945
+ </script>
946
+ </body>
947
+ </html>"""
948
 
949
  def apply_dark_theme():
950
  """Inject dark-theme CSS, flexible panel JS, card↔map hover JS, and smart image positioning JS."""