Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,12 @@ After completing a milestone, create a pull request with your changes for review
- [x] Enforce maximum file size during upload
- [x] Add tests covering oversized file uploads

## PR20: Theme Improvements

- [x] Extend sidebar and Plotly figure styling for both themes
- [x] Add global theme toggle stored in session state
- [x] Update tests to verify theme CSS output

## Notes for Development

- Create comprehensive commit messages that clearly describe changes
Expand Down
6 changes: 6 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

st.set_page_config(page_title="PredictStream", layout="wide")

if "theme" not in st.session_state:
st.session_state["theme"] = "Light"

ui.apply_theme(st.session_state["theme"])


def main() -> None:
"""Render the home page with navigation links."""
Expand All @@ -17,6 +22,7 @@ def main() -> None:
"Use the sidebar to navigate to different sections of the application."
)
with st.sidebar:
st.selectbox("Theme", ["Light", "Dark"], key="theme")
st.page_link("app.py", label="Home", icon="🏠")
st.page_link("pages/data_explorer.py", label="Data Explorer", icon="📊")
st.page_link("pages/modeling.py", label="Modeling", icon="🧠")
Expand Down
8 changes: 1 addition & 7 deletions pages/data_explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ def main() -> None:
"""Render the data exploration and modeling page."""
ui.apply_branding()
st.title("Data Explorer")
theme = st.sidebar.selectbox(
"Theme",
["Light", "Dark"],
help="Toggle interface theme",
key="theme",
)
st.markdown(ui.get_theme_css(theme), unsafe_allow_html=True)
ui.apply_theme()

with st.expander("Getting Started"):
st.markdown(ui.getting_started_markdown())
Expand Down
1 change: 1 addition & 0 deletions pages/modeling.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def main() -> None:
"""Render the modeling page."""
ui.apply_branding()
st.title("Modeling")
ui.apply_theme()

data_keys = _available_datasets()
if not data_keys:
Expand Down
1 change: 1 addition & 0 deletions pages/prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def main() -> None:
"""Render the prediction page."""
ui.apply_branding()
st.title("Prediction")
ui.apply_theme()

with st.sidebar:
mode = st.radio("Mode", ["Single", "Batch"], key="pred_mode")
Expand Down
1 change: 1 addition & 0 deletions pages/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def main() -> None:
"""Render the report generation page."""
ui.apply_branding()
st.title("Report Generator")
ui.apply_theme()

with st.sidebar:
data_utils.upload_data_to_session(
Expand Down
1 change: 1 addition & 0 deletions pages/time_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def main() -> None:
"""Render the time series analysis page."""
ui.apply_branding()
st.title("Time Series Analysis")
ui.apply_theme()

df = st.session_state.get("data")
if df is None or df.empty:
Expand Down
7 changes: 5 additions & 2 deletions tests/test_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@


def test_get_theme_css():
css = ui.get_theme_css("Dark")
assert "background-color" in css
light = ui.get_theme_css("Light")
dark = ui.get_theme_css("Dark")
for css in (light, dark):
assert "stSidebar" in css
assert "plotly-chart" in css


def test_getting_started_markdown():
Expand Down
22 changes: 20 additions & 2 deletions utils/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,19 @@
import streamlit as st

THEME_CSS: Dict[str, str] = {
"Light": "",
"Dark": "body { background-color: #0e1117; color: #f0f0f0; }",
"Light": """
<style>
[data-testid='stSidebar'] {background-color: #f0f2f6;}
.plotly-chart .main-svg {background-color: #ffffff;}
</style>
""",
"Dark": """
<style>
body {background-color: #0e1117; color: #f0f0f0;}
[data-testid='stSidebar'] {background-color: #262730;}
.plotly-chart .main-svg {background-color: #0e1117;}
</style>
""",
}

# Branding colors
Expand All @@ -31,6 +42,13 @@ def get_theme_css(theme: str) -> str:
return THEME_CSS.get(theme, "")


def apply_theme(theme: str | None = None) -> None:
"""Apply the selected theme's CSS to the app."""
if theme is None:
theme = st.session_state.get("theme", "Light")
st.markdown(get_theme_css(theme), unsafe_allow_html=True)


def getting_started_markdown() -> str:
"""Return markdown text for the getting started guide."""
return (
Expand Down