feat: Add floating sidebar navigation and dark theme support

- Add floating pill-shaped sidebar with navigation icons
- Implement dark/light theme toggle with localStorage persistence
- Update all figure factories for transparent backgrounds
- Use carto-darkmatter map style for choropleths
- Add methodology link button to Toronto dashboard header
- Add back to dashboard button on methodology page
- Remove social links from home page (now in sidebar)
- Update CLAUDE.md to Sprint 7

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-15 11:53:13 -05:00
parent 1e0ea9cca2
commit b3fb94c7cb
13 changed files with 475 additions and 49 deletions

View File

@@ -39,6 +39,10 @@ def create_choropleth_figure(
if center is None:
center = {"lat": 43.7, "lon": -79.4}
# Use dark-mode friendly map style by default
if map_style == "carto-positron":
map_style = "carto-darkmatter"
# If no geojson provided, create a placeholder map
if geojson is None or not data:
fig = go.Figure(go.Scattermapbox())
@@ -51,6 +55,9 @@ def create_choropleth_figure(
margin={"l": 0, "r": 0, "t": 40, "b": 0},
title=title or "Toronto Housing Map",
height=500,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
)
fig.add_annotation(
text="No geometry data available. Complete QGIS digitization to enable map.",
@@ -59,7 +66,7 @@ def create_choropleth_figure(
x=0.5,
y=0.5,
showarrow=False,
font={"size": 14, "color": "gray"},
font={"size": 14, "color": "#888888"},
)
return fig
@@ -68,6 +75,11 @@ def create_choropleth_figure(
df = pd.DataFrame(data)
# Use dark-mode friendly map style
effective_map_style = (
"carto-darkmatter" if map_style == "carto-positron" else map_style
)
fig = px.choropleth_mapbox(
df,
geojson=geojson,
@@ -76,7 +88,7 @@ def create_choropleth_figure(
color=color_column,
color_continuous_scale=color_scale,
hover_data=hover_data,
mapbox_style=map_style,
mapbox_style=effective_map_style,
center=center,
zoom=zoom,
opacity=0.7,
@@ -86,10 +98,17 @@ def create_choropleth_figure(
margin={"l": 0, "r": 0, "t": 40, "b": 0},
title=title,
height=500,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
coloraxis_colorbar={
"title": color_column.replace("_", " ").title(),
"title": {
"text": color_column.replace("_", " ").title(),
"font": {"color": "#c9c9c9"},
},
"thickness": 15,
"len": 0.7,
"tickfont": {"color": "#c9c9c9"},
},
)

View File

@@ -69,7 +69,8 @@ def create_metric_card_figure(
height=120,
margin={"l": 20, "r": 20, "t": 40, "b": 20},
paper_bgcolor="rgba(0,0,0,0)",
font={"family": "Inter, sans-serif"},
plot_bgcolor="rgba(0,0,0,0)",
font={"family": "Inter, sans-serif", "color": "#c9c9c9"},
)
return fig

View File

@@ -38,8 +38,15 @@ def create_price_time_series(
x=0.5,
y=0.5,
showarrow=False,
font={"color": "#888888"},
)
fig.update_layout(
title=title,
height=350,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
)
fig.update_layout(title=title, height=350)
return fig
df = pd.DataFrame(data)
@@ -69,6 +76,11 @@ def create_price_time_series(
yaxis_tickprefix="$",
yaxis_tickformat=",",
hovermode="x unified",
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
xaxis={"gridcolor": "#333333", "linecolor": "#444444"},
yaxis={"gridcolor": "#333333", "linecolor": "#444444"},
)
return fig
@@ -106,8 +118,15 @@ def create_volume_time_series(
x=0.5,
y=0.5,
showarrow=False,
font={"color": "#888888"},
)
fig.update_layout(
title=title,
height=350,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
)
fig.update_layout(title=title, height=350)
return fig
df = pd.DataFrame(data)
@@ -153,6 +172,11 @@ def create_volume_time_series(
yaxis_title=volume_column.replace("_", " ").title(),
yaxis_tickformat=",",
hovermode="x unified",
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
xaxis={"gridcolor": "#333333", "linecolor": "#444444"},
yaxis={"gridcolor": "#333333", "linecolor": "#444444"},
)
return fig
@@ -187,8 +211,15 @@ def create_market_comparison_chart(
x=0.5,
y=0.5,
showarrow=False,
font={"color": "#888888"},
)
fig.update_layout(
title=title,
height=400,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
)
fig.update_layout(title=title, height=400)
return fig
if metrics is None:
@@ -221,12 +252,18 @@ def create_market_comparison_chart(
height=400,
margin={"l": 40, "r": 40, "t": 50, "b": 40},
hovermode="x unified",
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
xaxis={"gridcolor": "#333333", "linecolor": "#444444"},
yaxis={"gridcolor": "#333333", "linecolor": "#444444"},
legend={
"orientation": "h",
"yanchor": "bottom",
"y": 1.02,
"xanchor": "right",
"x": 1,
"font": {"color": "#c9c9c9"},
},
)