Repository: streamlit/streamlit

Issue:
st.map should become dark when app is in dark mode
Right now all our Vega-Lite based charts (st.altair_chart, st.line_chart, etc.) follow the user theme. For st.map and PyDeck it's not as easy to make them follow the exact theme, but we could at least make them use [the dark map](https://deckgl.readthedocs.io/en/latest/gallery/grid_layer.html) style when the app is show in Streamlit's dark theme with no overrides.

This line currently fixes the map style to light:
https://github.com/streamlit/streamlit/blob/96f17464a13969ecdfe31043ab8e875718eb0d10/lib/streamlit/elements/map.py#L85

So what I'm proposing is that we could instead flip between light and dark (probably in JS) based on the theme.


Discussion:
Hey @tvst, I have used streamlit a couple of times now and I want to contribute something to streamlit. I have understood this issue clearly and want to work on this. Can you please assign me this issue and help me how to get started with it?
Hey @psyduck1203 Thanks for volunteering and sorry for the slow response! If you are still interested, feel free to do it. It may need some investigation to ensure this works correctly for all purposes. Feel free to reach out if you need any guidance.
Yeah, I'm interested and I want to work on this issue. I'll surely ask you if I get stuck.
+1

Resolving patch:
diff --git a/lib/streamlit/elements/deck_gl_json_chart.py b/lib/streamlit/elements/deck_gl_json_chart.py
--- a/lib/streamlit/elements/deck_gl_json_chart.py
+++ b/lib/streamlit/elements/deck_gl_json_chart.py
@@ -12,10 +12,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from typing import cast, Any, Dict
+import json
+from typing import Any, Dict, cast
+
+import pydeck as pdk
 
 import streamlit
-import json
 from streamlit.proto.DeckGlJsonChart_pb2 import DeckGlJsonChart as PydeckProto
 
 
@@ -55,7 +57,6 @@ def pydeck_chart(self, pydeck_obj=None, use_container_width=False):
         ...    columns=['lat', 'lon'])
         >>>
         >>> st.pydeck_chart(pdk.Deck(
-        ...     map_style='mapbox://styles/mapbox/light-v9',
         ...     initial_view_state=pdk.ViewState(
         ...         latitude=37.76,
         ...         longitude=-122.4,
@@ -100,7 +101,7 @@ def dg(self) -> "streamlit.delta_generator.DeltaGenerator":
 
 # Map used when no data is passed.
 EMPTY_MAP: Dict[str, Any] = {
-    "initialViewState": {"latitude": 0, "longitude": 0, "pitch": 0, "zoom": 1}
+    "initialViewState": {"latitude": 0, "longitude": 0, "pitch": 0, "zoom": 1},
 }
 
 
diff --git a/lib/streamlit/elements/map.py b/lib/streamlit/elements/map.py
--- a/lib/streamlit/elements/map.py
+++ b/lib/streamlit/elements/map.py
@@ -16,8 +16,7 @@
 
 import copy
 import json
-from typing import Any, Dict
-from typing import cast
+from typing import Any, Dict, cast
 
 import pandas as pd
 
@@ -83,7 +82,6 @@ def dg(self) -> "streamlit.delta_generator.DeltaGenerator":
 
 # Map used as the basis for st.map.
 _DEFAULT_MAP = dict(deck_gl_json_chart.EMPTY_MAP)  # type: Dict[str, Any]
-_DEFAULT_MAP["mapStyle"] = "mapbox://styles/mapbox/light-v10"
 
 # Other default parameters for st.map.
 _DEFAULT_COLOR = [200, 30, 0, 160]
diff --git "a/lib/streamlit/hello/pages/2_\360\237\214\215_Mapping_Demo.py" "b/lib/streamlit/hello/pages/2_\360\237\214\215_Mapping_Demo.py"
--- "a/lib/streamlit/hello/pages/2_\360\237\214\215_Mapping_Demo.py"
+++ "b/lib/streamlit/hello/pages/2_\360\237\214\215_Mapping_Demo.py"
@@ -12,15 +12,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import streamlit as st
 import inspect
 import textwrap
+from urllib.error import URLError
+
 import pandas as pd
 import pydeck as pdk
-from streamlit.hello.utils import show_code
 
-
-from urllib.error import URLError
+import streamlit as st
+from streamlit.hello.utils import show_code
 
 
 def mapping_demo():


Test patch:
diff --git a/frontend/src/components/elements/DeckGlJsonChart/DeckGlJsonChart.test.tsx b/frontend/src/components/elements/DeckGlJsonChart/DeckGlJsonChart.test.tsx
--- a/frontend/src/components/elements/DeckGlJsonChart/DeckGlJsonChart.test.tsx
+++ b/frontend/src/components/elements/DeckGlJsonChart/DeckGlJsonChart.test.tsx
@@ -18,6 +18,7 @@
 import React from "react"
 import DeckGL from "deck.gl"
 import { shallow } from "src/lib/test_util"
+import { lightTheme } from "src/theme"
 
 import { DeckGlJsonChart as DeckGlJsonChartProto } from "src/autogen/proto"
 import { DeckGlJsonChart, PropsWithHeight } from "./DeckGlJsonChart"
@@ -26,8 +27,34 @@ const getProps = (
   elementProps: Partial<DeckGlJsonChartProto> = {},
   initialViewStateProps: Record<string, unknown> = {}
 ): PropsWithHeight => {
-  // prettier-ignore
-  const json = {"initialViewState": {"bearing": -27.36, "latitude": 52.2323, "longitude": -1.415, "maxZoom": 15, "minZoom": 5, "pitch": 40.5, "zoom": 6}, "layers": [{"@@type": "HexagonLayer", "autoHighlight": true, "coverage": 1, "data": "https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv", "elevationRange": [0, 3000], "elevationScale": 50, "extruded": true, "getPosition": "@@=[lng, lat]", "id": "0533490f-fcf9-4dc0-8c94-ae4fbd42eb6f", "pickable": true}], "mapStyle": "mapbox://styles/mapbox/light-v9", "views": [{"@@type": "MapView", "controller": true}]}
+  const json = {
+    initialViewState: {
+      bearing: -27.36,
+      latitude: 52.2323,
+      longitude: -1.415,
+      maxZoom: 15,
+      minZoom: 5,
+      pitch: 40.5,
+      zoom: 6,
+    },
+    layers: [
+      {
+        "@@type": "HexagonLayer",
+        autoHighlight: true,
+        coverage: 1,
+        data:
+          "https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv",
+        elevationRange: [0, 3000],
+        elevationScale: 50,
+        extruded: true,
+        getPosition: "@@=[lng, lat]",
+        id: "0533490f-fcf9-4dc0-8c94-ae4fbd42eb6f",
+        pickable: true,
+      },
+    ],
+    mapStyle: "mapbox://styles/mapbox/light-v9",
+    views: [{ "@@type": "MapView", controller: true }],
+  }
 
   json.initialViewState = {
     ...json.initialViewState,
@@ -42,6 +69,7 @@ const getProps = (
     width: 0,
     mapboxToken: "mapboxToken",
     height: undefined,
+    theme: lightTheme.emotion,
   }
 }
 
diff --git a/lib/tests/streamlit/map_test.py b/lib/tests/streamlit/map_test.py
--- a/lib/tests/streamlit/map_test.py
+++ b/lib/tests/streamlit/map_test.py
@@ -14,13 +14,14 @@
 
 """Unit tests for st.map()."""
 
-import pandas as pd
-import numpy as np
 import json
 
-from streamlit.elements.map import _DEFAULT_MAP, _DEFAULT_ZOOM_LEVEL
+import numpy as np
+import pandas as pd
 from tests import testutil
+
 import streamlit as st
+from streamlit.elements.map import _DEFAULT_MAP, _DEFAULT_ZOOM_LEVEL
 
 df1 = pd.DataFrame({"lat": [1, 2, 3, 4], "lon": [10, 20, 30, 40]})
 
@@ -43,7 +44,7 @@ def test_basic(self):
 
         self.assertIsNotNone(c.get("initialViewState"))
         self.assertIsNotNone(c.get("layers"))
-        self.assertIsNotNone(c.get("mapStyle"))
+        self.assertIsNone(c.get("mapStyle"))
         self.assertEqual(len(c.get("layers")), 1)
         self.assertEqual(c.get("initialViewState").get("latitude"), 2.5)
         self.assertEqual(c.get("initialViewState").get("longitude"), 25)