diff --git a/Background_Dark.jpg b/Background_Dark.jpg
new file mode 100644
index 0000000..91e0d73
Binary files /dev/null and b/Background_Dark.jpg differ
diff --git a/TalkHeal.py b/TalkHeal.py
index e0068fa..6597dbe 100644
--- a/TalkHeal.py
+++ b/TalkHeal.py
@@ -41,16 +41,6 @@
model = configure_gemini()
-col_toggle, col_main = st.columns([0.05, 0.95])
-
-with col_toggle:
- if st.button("â°", key="persistent_sidebar_toggle", help="Toggle Sidebar"):
- if st.session_state.sidebar_state == "expanded":
- st.session_state.sidebar_state = "collapsed"
- else:
- st.session_state.sidebar_state = "expanded"
- st.rerun()
-
render_sidebar()
render_header()
diff --git a/blue.png b/blue.png
new file mode 100644
index 0000000..25ecc70
Binary files /dev/null and b/blue.png differ
diff --git a/components/__pycache__/__init__.cpython-313.pyc b/components/__pycache__/__init__.cpython-313.pyc
index b5eb29b..171d2dd 100644
Binary files a/components/__pycache__/__init__.cpython-313.pyc and b/components/__pycache__/__init__.cpython-313.pyc differ
diff --git a/components/__pycache__/chat_interface.cpython-313.pyc b/components/__pycache__/chat_interface.cpython-313.pyc
index c6cb3be..c6e50f5 100644
Binary files a/components/__pycache__/chat_interface.cpython-313.pyc and b/components/__pycache__/chat_interface.cpython-313.pyc differ
diff --git a/components/__pycache__/header.cpython-313.pyc b/components/__pycache__/header.cpython-313.pyc
index 3599f89..333a96c 100644
Binary files a/components/__pycache__/header.cpython-313.pyc and b/components/__pycache__/header.cpython-313.pyc differ
diff --git a/components/__pycache__/sidebar.cpython-313.pyc b/components/__pycache__/sidebar.cpython-313.pyc
index 6b26cef..7b7f4d1 100644
Binary files a/components/__pycache__/sidebar.cpython-313.pyc and b/components/__pycache__/sidebar.cpython-313.pyc differ
diff --git a/components/__pycache__/theme_toggle.cpython-313.pyc b/components/__pycache__/theme_toggle.cpython-313.pyc
new file mode 100644
index 0000000..aea237e
Binary files /dev/null and b/components/__pycache__/theme_toggle.cpython-313.pyc differ
diff --git a/components/chat_interface.py b/components/chat_interface.py
index c7b52e7..a0343c8 100644
--- a/components/chat_interface.py
+++ b/components/chat_interface.py
@@ -1,5 +1,6 @@
import streamlit as st
from core.utils import get_current_time, get_ai_response
+from core.theme import toggle_theme, get_current_theme
import streamlit.components.v1 as components
import streamlit as st
diff --git a/components/header.py b/components/header.py
index c8ec43b..c419e22 100644
--- a/components/header.py
+++ b/components/header.py
@@ -4,6 +4,24 @@
def render_header():
with st.container():
+ # Top bar with hamburger menu and theme toggle
+ col1, col2, col3 = st.columns([0.1, 0.8, 0.1])
+
+ with col1:
+ if st.button("â°", key="top_hamburger_menu", help="Toggle Sidebar", use_container_width=True):
+ if st.session_state.sidebar_state == "expanded":
+ st.session_state.sidebar_state = "collapsed"
+ else:
+ st.session_state.sidebar_state = "expanded"
+ st.rerun()
+
+ with col3:
+ is_dark = st.session_state.get('dark_mode', False)
+ if st.button("đ" if is_dark else "âī¸", key="top_theme_toggle", help="Toggle Light/Dark Mode", use_container_width=True):
+ st.session_state.dark_mode = not is_dark
+ st.session_state.theme_changed = True
+ st.rerun()
+
st.markdown("""
TalkHeal
diff --git a/components/sidebar.py b/components/sidebar.py
index 6d9aeee..7765a57 100644
--- a/components/sidebar.py
+++ b/components/sidebar.py
@@ -2,6 +2,7 @@
import webbrowser
from datetime import datetime
from core.utils import create_new_conversation, get_current_time
+from core.theme import get_current_theme, toggle_theme, set_palette, PALETTES
# Emergency contacts and resources
emergency_resources = {
@@ -288,6 +289,44 @@ def render_sidebar():
for number in numbers:
st.markdown(f"âĸ {number}")
+ # Theme toggle in sidebar
+ with st.expander("đ¨ Theme Settings"):
+ current_theme = get_current_theme()
+ is_dark = current_theme["name"] == "Dark"
+
+ # Palette selector (only for light mode)
+ if not is_dark:
+ palette_names = [p["name"] for p in PALETTES]
+ selected_palette = st.selectbox(
+ "Choose a soothing color palette:",
+ palette_names,
+ index=palette_names.index(st.session_state.get("palette_name", "Light")),
+ key="palette_selector",
+ )
+ if selected_palette != st.session_state.get("palette_name", "Light"):
+ set_palette(selected_palette)
+
+ # Current theme display with better styling
+ st.markdown("""
+
+ Current Theme:
+ {} Mode
+
+ """.format(current_theme['name']), unsafe_allow_html=True)
+
+ # Theme toggle button with better styling
+ button_text = "đ Dark Mode" if not is_dark else "âī¸ Light Mode"
+ button_color = "primary" if not is_dark else "secondary"
+
+ if st.button(
+ button_text,
+ key="sidebar_theme_toggle",
+ use_container_width=True,
+ type=button_color
+ ):
+ toggle_theme()
+
+
with st.expander("âšī¸ About TalkHeal"):
st.markdown("""
**TalkHeal** is your compassionate mental health companion, designed to provide:
diff --git a/components/theme_toggle.py b/components/theme_toggle.py
new file mode 100644
index 0000000..e4e2dd1
--- /dev/null
+++ b/components/theme_toggle.py
@@ -0,0 +1,68 @@
+import streamlit as st
+from core.theme import toggle_theme, get_current_theme
+
+def render_theme_toggle():
+ """Render the theme toggle button in the top right corner."""
+ current_theme = get_current_theme()
+ is_dark = current_theme["name"] == "Dark"
+
+ # Create a container for the theme toggle
+ with st.container():
+ # Use columns to position the toggle on the right
+ col1, col2, col3 = st.columns([0.7, 0.2, 0.1])
+
+ with col3:
+ # Theme toggle button
+ button_text = "đ Dark Mode" if is_dark else "âī¸ Light Mode"
+ button_color = "primary" if is_dark else "secondary"
+
+ if st.button(
+ button_text,
+ key="theme_toggle",
+ help="Toggle Light/Dark Mode",
+ use_container_width=True,
+ type=button_color
+ ):
+ toggle_theme()
+
+ # Add some custom CSS to style the toggle button
+ st.markdown("""
+
+ """, unsafe_allow_html=True)
\ No newline at end of file
diff --git a/core/__pycache__/__init__.cpython-313.pyc b/core/__pycache__/__init__.cpython-313.pyc
index 0c7aeb7..ae8bca5 100644
Binary files a/core/__pycache__/__init__.cpython-313.pyc and b/core/__pycache__/__init__.cpython-313.pyc differ
diff --git a/core/__pycache__/config.cpython-313.pyc b/core/__pycache__/config.cpython-313.pyc
index aab7895..190a42e 100644
Binary files a/core/__pycache__/config.cpython-313.pyc and b/core/__pycache__/config.cpython-313.pyc differ
diff --git a/core/__pycache__/theme.cpython-313.pyc b/core/__pycache__/theme.cpython-313.pyc
new file mode 100644
index 0000000..face49c
Binary files /dev/null and b/core/__pycache__/theme.cpython-313.pyc differ
diff --git a/core/__pycache__/utils.cpython-313.pyc b/core/__pycache__/utils.cpython-313.pyc
index 84cbc69..33e809a 100644
Binary files a/core/__pycache__/utils.cpython-313.pyc and b/core/__pycache__/utils.cpython-313.pyc differ
diff --git a/core/theme.py b/core/theme.py
new file mode 100644
index 0000000..a52edc3
--- /dev/null
+++ b/core/theme.py
@@ -0,0 +1,249 @@
+import streamlit as st
+from typing import Dict, Any
+
+# Light theme (current default)
+LIGHT_THEME = {
+ "name": "Light",
+ "background_image": "Background.jpg",
+ "primary": "#6366f1",
+ "primary_light": "#818cf8",
+ "primary_dark": "#4f46e5",
+ "secondary": "#ec4899",
+ "success": "#10b981",
+ "warning": "#f59e0b",
+ "danger": "#ef4444",
+ "surface": "rgba(255, 255, 255, 0.15)",
+ "surface_alt": "rgba(255, 255, 255, 0.25)",
+ "text_primary": "#1e293b",
+ "text_secondary": "#64748b",
+ "text_muted": "#94a3b8",
+ "border": "rgba(255, 255, 255, 0.3)",
+ "border_light": "rgba(255, 255, 255, 0.2)",
+ "shadow": "rgba(0, 0, 0, 0.15)",
+ "shadow_lg": "rgba(0, 0, 0, 0.25)",
+ "light_transparent_bg": "rgba(255, 255, 255, 0.4)",
+ "light_transparent_bg_hover": "rgba(255, 255, 255, 0.6)",
+ "light_transparent_border": "rgba(255, 255, 255, 0.5)",
+ "active_conversation_bg": "linear-gradient(135deg, rgba(99, 102, 241, 0.9) 0%, rgba(129, 140, 248, 0.9) 100%)",
+ "active_conversation_border": "rgba(99, 102, 241, 0.8)",
+ "active_conversation_shadow": "rgba(99, 102, 241, 0.4)",
+ "background_overlay": "rgba(0, 0, 0, 0.3)",
+ "main_text_color": "white",
+ "sidebar_bg": "rgba(255, 255, 255, 0.15)",
+ "sidebar_text": "#1e293b",
+ "input_bg": "purple",
+ "input_text": "white"
+}
+
+# Additional soothing palettes
+CALM_BLUE = {
+ "name": "Calm Blue",
+ "background_image": "blue.png",
+ "background_gradient": "linear-gradient(135deg, #3674B5 0%, #578FCA 40%, #A1E3F9 75%, #D1F8EF 100%)",
+ "primary": "#3674B5",
+ "primary_light": "#578FCA",
+ "primary_dark": "#3674B5",
+ "secondary": "#A1E3F9",
+ "success": "#578FCA",
+ "warning": "#A1E3F9",
+ "danger": "#D1F8EF",
+ "surface": "rgba(255, 255, 255, 0.25)",
+ "surface_alt": "rgba(255, 255, 255, 0.35)",
+ "text_primary": "#2d3436",
+ "text_secondary": "#636e72",
+ "text_muted": "#b2bec3",
+ "border": "rgba(87, 143, 202, 0.2)",
+ "border_light": "rgba(87, 143, 202, 0.1)",
+ "shadow": "rgba(87, 143, 202, 0.08)",
+ "shadow_lg": "rgba(87, 143, 202, 0.15)",
+ "light_transparent_bg": "rgba(255, 255, 255, 0.5)",
+ "light_transparent_bg_hover": "rgba(255, 255, 255, 0.7)",
+ "light_transparent_border": "rgba(87, 143, 202, 0.2)",
+ "active_conversation_bg": "linear-gradient(135deg, #3674B5 0%, #578FCA 60%, #A1E3F9 100%)",
+ "active_conversation_border": "#3674B5",
+ "active_conversation_shadow": "rgba(87, 143, 202, 0.2)",
+ "background_overlay": "rgba(255, 255, 255, 0.2)",
+ "main_text_color": "#2d3436",
+ "sidebar_bg": "rgba(255, 255, 255, 0.25)",
+ "sidebar_text": "#2d3436",
+ "input_bg": "#D1F8EF",
+ "input_text": "#2d3436"
+}
+
+MINT = {
+ "name": "Mint",
+ "background_image": "mint.png",
+ "background_gradient": "linear-gradient(135deg, #3D8D7A 0%, #B3D8A8 40%, #FBFFE4 75%, #A3D1C6 100%)",
+ "primary": "#3D8D7A",
+ "primary_light": "#B3D8A8",
+ "primary_dark": "#3D8D7A",
+ "secondary": "#FBFFE4",
+ "success": "#B3D8A8",
+ "warning": "#A3D1C6",
+ "danger": "#FBFFE4",
+ "surface": "rgba(255, 255, 255, 0.25)",
+ "surface_alt": "rgba(255, 255, 255, 0.35)",
+ "text_primary": "#2d3436",
+ "text_secondary": "#636e72",
+ "text_muted": "#b2bec3",
+ "border": "rgba(179, 216, 168, 0.2)",
+ "border_light": "rgba(179, 216, 168, 0.1)",
+ "shadow": "rgba(179, 216, 168, 0.08)",
+ "shadow_lg": "rgba(179, 216, 168, 0.15)",
+ "light_transparent_bg": "rgba(255, 255, 255, 0.5)",
+ "light_transparent_bg_hover": "rgba(255, 255, 255, 0.7)",
+ "light_transparent_border": "rgba(179, 216, 168, 0.2)",
+ "active_conversation_bg": "linear-gradient(135deg, #3D8D7A 0%, #B3D8A8 60%, #A3D1C6 100%)",
+ "active_conversation_border": "#3D8D7A",
+ "active_conversation_shadow": "rgba(179, 216, 168, 0.2)",
+ "background_overlay": "rgba(255, 255, 255, 0.2)",
+ "main_text_color": "#2C3930",
+ "sidebar_bg": "rgba(255, 255, 255, 0.25)",
+ "sidebar_text": "#2C3930",
+ "input_bg": "#FBFFE4",
+ "input_text": "#2C3930"
+}
+
+LAVENDER = {
+ "name": "Lavender",
+ "background_image": "lavender.png",
+ "background_gradient": "linear-gradient(135deg, #756AB6 0%, #AC87C5 40%, #E0AED0 75%, #FFE5E5 100%)",
+ "primary": "#756AB6",
+ "primary_light": "#AC87C5",
+ "primary_dark": "#756AB6",
+ "secondary": "#E0AED0",
+ "success": "#AC87C5",
+ "warning": "#E0AED0",
+ "danger": "#FFE5E5",
+ "surface": "rgba(255, 255, 255, 0.25)",
+ "surface_alt": "rgba(255, 255, 255, 0.35)",
+ "text_primary": "#2d3436",
+ "text_secondary": "#636e72",
+ "text_muted": "#b2bec3",
+ "border": "rgba(172, 135, 197, 0.2)",
+ "border_light": "rgba(172, 135, 197, 0.1)",
+ "shadow": "rgba(172, 135, 197, 0.08)",
+ "shadow_lg": "rgba(172, 135, 197, 0.15)",
+ "light_transparent_bg": "rgba(255, 255, 255, 0.5)",
+ "light_transparent_bg_hover": "rgba(255, 255, 255, 0.7)",
+ "light_transparent_border": "rgba(172, 135, 197, 0.2)",
+ "active_conversation_bg": "linear-gradient(135deg, #756AB6 0%, #AC87C5 60%, #E0AED0 100%)",
+ "active_conversation_border": "#756AB6",
+ "active_conversation_shadow": "rgba(172, 135, 197, 0.2)",
+ "background_overlay": "rgba(255, 255, 255, 0.2)",
+ "main_text_color": "#2d3436",
+ "sidebar_bg": "rgba(255, 255, 255, 0.25)",
+ "sidebar_text": "#2d3436",
+ "input_bg": "#FFE5E5",
+ "input_text": "#2d3436"
+}
+
+Pink = {
+ "name": "Pink",
+ "background_image": "pink.png",
+ "background_gradient": "linear-gradient(135deg, #921A40 0%, #C75B7A 40%, #D9ABAB 75%, #F4D9D0 100%)",
+ "primary": "#921A40",
+ "primary_light": "#C75B7A",
+ "primary_dark": "#921A40",
+ "secondary": "#D9ABAB",
+ "success": "#C75B7A",
+ "warning": "#D9ABAB",
+ "danger": "#F4D9D0",
+ "surface": "rgba(255, 255, 255, 0.25)",
+ "surface_alt": "rgba(255, 255, 255, 0.35)",
+ "text_primary": "#2d3436",
+ "text_secondary": "#636e72",
+ "text_muted": "#b2bec3",
+ "border": "rgba(199, 91, 122, 0.2)",
+ "border_light": "rgba(199, 91, 122, 0.1)",
+ "shadow": "rgba(199, 91, 122, 0.08)",
+ "shadow_lg": "rgba(199, 91, 122, 0.15)",
+ "light_transparent_bg": "rgba(255, 255, 255, 0.5)",
+ "light_transparent_bg_hover": "rgba(255, 255, 255, 0.7)",
+ "light_transparent_border": "rgba(199, 91, 122, 0.2)",
+ "active_conversation_bg": "linear-gradient(135deg, #921A40 0%, #C75B7A 60%, #D9ABAB 100%)",
+ "active_conversation_border": "#921A40",
+ "active_conversation_shadow": "rgba(199, 91, 122, 0.2)",
+ "background_overlay": "rgba(255, 255, 255, 0.2)",
+ "main_text_color": "#2d3436",
+ "sidebar_bg": "rgba(255, 255, 255, 0.25)",
+ "sidebar_text": "#2d3436",
+ "input_bg": "#F4D9D0",
+ "input_text": "#2d3436"
+}
+
+# Dark theme
+DARK_THEME = {
+ "name": "Dark",
+ "background_image": "dark.png",
+ "primary": "#6366f1",
+ "primary_light": "#818cf8",
+ "primary_dark": "#4f46e5",
+ "secondary": "#ec4899",
+ "success": "#10b981",
+ "warning": "#f59e0b",
+ "danger": "#ef4444",
+ "surface": "rgba(0, 0, 0, 0.4)",
+ "surface_alt": "rgba(0, 0, 0, 0.5)",
+ "text_primary": "#f8fafc",
+ "text_secondary": "#cbd5e1",
+ "text_muted": "#94a3b8",
+ "border": "rgba(255, 255, 255, 0.2)",
+ "border_light": "rgba(255, 255, 255, 0.1)",
+ "shadow": "rgba(0, 0, 0, 0.4)",
+ "shadow_lg": "rgba(0, 0, 0, 0.6)",
+ "light_transparent_bg": "rgba(0, 0, 0, 0.5)",
+ "light_transparent_bg_hover": "rgba(0, 0, 0, 0.7)",
+ "light_transparent_border": "rgba(255, 255, 255, 0.2)",
+ "active_conversation_bg": "linear-gradient(135deg, rgba(99, 102, 241, 0.8) 0%, rgba(129, 140, 248, 0.8) 100%)",
+ "active_conversation_border": "rgba(99, 102, 241, 0.6)",
+ "active_conversation_shadow": "rgba(99, 102, 241, 0.3)",
+ "background_overlay": "rgba(0, 0, 0, 0.6)",
+ "main_text_color": "#f8fafc",
+ "sidebar_bg": "rgba(0, 0, 0, 0.4)",
+ "sidebar_text": "#f8fafc",
+ "input_bg": "#374151",
+ "input_text": "#f8fafc"
+}
+
+PALETTES = [
+ LIGHT_THEME,
+ CALM_BLUE,
+ MINT,
+ LAVENDER,
+ Pink
+]
+
+PALETTE_NAME_TO_CONFIG = {p["name"]: p for p in PALETTES}
+
+
+def initialize_theme_state():
+ """Initialize theme-related session state variables."""
+ if "dark_mode" not in st.session_state:
+ st.session_state.dark_mode = False
+ if "theme_changed" not in st.session_state:
+ st.session_state.theme_changed = False
+ if "palette_name" not in st.session_state:
+ st.session_state.palette_name = "Light"
+
+
+def get_current_theme() -> Dict[str, Any]:
+ """Get the current theme configuration based on session state."""
+ initialize_theme_state()
+ if st.session_state.dark_mode:
+ return DARK_THEME
+ else:
+ palette = PALETTE_NAME_TO_CONFIG.get(st.session_state.get("palette_name", "Light"), LIGHT_THEME)
+ return palette
+
+def set_palette(palette_name: str):
+ st.session_state.palette_name = palette_name
+ st.session_state.theme_changed = True
+ st.rerun()
+
+def toggle_theme():
+ """Toggle between light and dark themes."""
+ initialize_theme_state()
+ st.session_state.dark_mode = not st.session_state.dark_mode
+ st.session_state.theme_changed = True
+ st.rerun()
\ No newline at end of file
diff --git a/css/__pycache__/styles.cpython-313.pyc b/css/__pycache__/styles.cpython-313.pyc
index 5fe2de4..afa6719 100644
Binary files a/css/__pycache__/styles.cpython-313.pyc and b/css/__pycache__/styles.cpython-313.pyc differ
diff --git a/css/styles.py b/css/styles.py
index 37fe904..b2399aa 100644
--- a/css/styles.py
+++ b/css/styles.py
@@ -8,11 +8,27 @@ def get_base64_of_bin_file(bin_file):
return base64.b64encode(data).decode()
def apply_custom_css():
- # Path to your background image
- background_image_path = "Background.jpg"
+ # Import theme configuration
+ from core.theme import get_current_theme
+ theme_config = get_current_theme()
- # Encode the image to base64
- base64_image = get_base64_of_bin_file(background_image_path)
+ # Path to background image based on theme
+ background_image_path = theme_config.get('background_image', 'Background.jpg')
+ background_gradient = theme_config.get('background_gradient', None)
+
+ base64_image = None
+ if background_image_path:
+ try:
+ base64_image = get_base64_of_bin_file(background_image_path)
+ except Exception:
+ base64_image = None
+
+ if base64_image:
+ background_css = f'background-image: url("data:image/jpeg;base64,{base64_image}");'
+ elif background_gradient:
+ background_css = f'background-image: {background_gradient};'
+ else:
+ background_css = ''
st.markdown(f"""
""", unsafe_allow_html=True)
\ No newline at end of file
diff --git a/dark.png b/dark.png
new file mode 100644
index 0000000..c2fae89
Binary files /dev/null and b/dark.png differ
diff --git a/lavender.png b/lavender.png
new file mode 100644
index 0000000..09135cf
Binary files /dev/null and b/lavender.png differ
diff --git a/mint.png b/mint.png
new file mode 100644
index 0000000..cdeb254
Binary files /dev/null and b/mint.png differ
diff --git a/pink.png b/pink.png
new file mode 100644
index 0000000..96b8df8
Binary files /dev/null and b/pink.png differ