Danialebrat's picture
Deploying new UI for AI messaging system
822ac98
"""
Brand-specific theming module for the AI Messaging System Visualization Tool.
Provides dynamic color schemes and styling based on selected brand.
"""
import streamlit as st
from typing import Dict, Tuple
# Brand color definitions (primary, secondary, accent)
BRAND_COLORS = {
"base": {
"primary": "#FFD700", # Gold
"secondary": "#2C2C2C", # Dark gray
"accent": "#1A1A1A", # Black
"text": "#FFFFFF", # White
"background": "#0D0D0D", # Very dark
"sidebar_bg": "#8B7500" # Darker gold for sidebar
},
"drumeo": {
"primary": "#5DADE2", # Light blue
"secondary": "#FFD700", # Gold
"accent": "#2874A6", # Darker blue
"text": "#FFFFFF", # White
"background": "#1C2833", # Dark blue-gray
"sidebar_bg": "#1A4D6B" # Darker blue for sidebar
},
"pianote": {
"primary": "#EC7063", # Light red
"secondary": "#FFD700", # Gold
"accent": "#C0392B", # Darker red
"text": "#FFFFFF", # White
"background": "#1C1C1C", # Dark
"sidebar_bg": "#8B2500" # Darker red for sidebar
},
"guitareo": {
"primary": "#58D68D", # Light green
"secondary": "#FFD700", # Gold
"accent": "#229954", # Darker green
"text": "#FFFFFF", # White
"background": "#1C2E1F", # Dark green-gray
"sidebar_bg": "#1B5E20" # Darker green for sidebar
},
"singeo": {
"primary": "#BB8FCE", # Light purple
"secondary": "#FFD700", # Gold
"accent": "#7D3C98", # Darker purple
"text": "#FFFFFF", # White
"background": "#1F1926", # Dark purple-gray
"sidebar_bg": "#4A148C" # Darker purple for sidebar
}
}
# Brand emojis
BRAND_EMOJIS = {
"drumeo": "🥁",
"pianote": "🎹",
"guitareo": "🎸",
"singeo": "🎤"
}
def get_brand_theme(brand: str) -> Dict[str, str]:
"""
Get color theme for specified brand.
Args:
brand: Brand name (drumeo, pianote, guitareo, singeo)
Returns:
dict: Color theme dictionary
"""
brand_lower = brand.lower() if brand else "base"
return BRAND_COLORS.get(brand_lower, BRAND_COLORS["base"])
def get_brand_emoji(brand: str) -> str:
"""
Get emoji for specified brand.
Args:
brand: Brand name
Returns:
str: Brand emoji
"""
brand_lower = brand.lower() if brand else ""
return BRAND_EMOJIS.get(brand_lower, "🎵")
def apply_theme(brand: str = None):
"""
Apply brand-specific theme to Streamlit app.
Args:
brand: Brand name (optional, uses session state if not provided)
"""
if brand is None:
brand = st.session_state.get("selected_brand", "base")
theme = get_brand_theme(brand)
# Custom CSS for brand theming
css = f"""
<style>
/* Global styles */
.stApp {{
background-color: {theme['background']};
}}
/* Text colors */
h1, h2, h3, h4, h5, h6 {{
color: {theme['primary']} !important;
}}
p, span, div {{
color: {theme['text']} !important;
}}
/* Button styles */
.stButton > button {{
background-color: {theme['primary']};
color: {theme['background']};
border: none;
border-radius: 8px;
padding: 0.5rem 1rem;
font-weight: 600;
transition: all 0.3s ease;
}}
.stButton > button:hover {{
background-color: {theme['secondary']};
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}}
/* Download button */
.stDownloadButton > button {{
background-color: {theme['accent']};
color: {theme['text']};
border-radius: 8px;
font-weight: 600;
}}
/* Input fields */
.stTextInput > div > div > input,
.stTextArea > div > div > textarea,
.stNumberInput > div > div > input {{
background-color: {theme['secondary']};
color: {theme['text']};
border: 1px solid {theme['primary']};
border-radius: 5px;
}}
/* Select boxes */
.stSelectbox > div > div {{
background-color: {theme['secondary']};
color: {theme['text']};
border-radius: 5px;
}}
/* Multiselect */
.stMultiSelect > div > div {{
background-color: {theme['secondary']};
border-radius: 5px;
}}
/* Tabs */
.stTabs [data-baseweb="tab-list"] {{
gap: 8px;
}}
.stTabs [data-baseweb="tab"] {{
background-color: {theme['secondary']};
color: {theme['text']};
border-radius: 5px 5px 0 0;
padding: 10px 20px;
font-weight: 600;
}}
.stTabs [aria-selected="true"] {{
background-color: {theme['primary']};
color: {theme['background']};
}}
/* Progress bar */
.stProgress > div > div > div {{
background-color: {theme['primary']};
}}
/* Expanders */
.streamlit-expanderHeader {{
background-color: {theme['secondary']};
color: {theme['primary']};
border-radius: 5px;
font-weight: 600;
}}
/* Cards/Containers */
.element-container {{
background-color: transparent;
}}
/* Sidebar */
[data-testid="stSidebar"] {{
background-color: {theme['sidebar_bg']};
}}
[data-testid="stSidebar"] h1,
[data-testid="stSidebar"] h2,
[data-testid="stSidebar"] h3 {{
color: {theme['text']} !important;
}}
[data-testid="stSidebar"] p,
[data-testid="stSidebar"] span,
[data-testid="stSidebar"] div,
[data-testid="stSidebar"] label {{
color: {theme['text']} !important;
}}
/* Metrics */
[data-testid="stMetricValue"] {{
color: {theme['primary']} !important;
font-size: 2rem;
font-weight: bold;
}}
/* Divider */
hr {{
border-color: {theme['primary']};
opacity: 0.3;
}}
/* Checkbox */
.stCheckbox {{
color: {theme['text']};
}}
/* Radio */
.stRadio > div {{
color: {theme['text']};
}}
/* Success/Info/Warning/Error boxes */
.stSuccess {{
background-color: rgba(88, 214, 141, 0.1);
color: {theme['text']};
}}
.stInfo {{
background-color: rgba(93, 173, 226, 0.1);
color: {theme['text']};
}}
.stWarning {{
background-color: rgba(255, 215, 0, 0.1);
color: {theme['text']};
}}
.stError {{
background-color: rgba(236, 112, 99, 0.1);
color: {theme['text']};
}}
/* DataFrames */
.dataframe {{
border: 1px solid {theme['primary']};
}}
/* Custom card styling */
.message-card {{
background-color: {theme['secondary']};
border-left: 4px solid {theme['primary']};
border-radius: 8px;
padding: 1rem;
margin: 0.5rem 0;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}}
.message-card:hover {{
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
transform: translateX(4px);
transition: all 0.3s ease;
}}
/* Small text */
.small {{
font-size: 0.85rem;
opacity: 0.7;
}}
/* Badge styles */
.badge {{
display: inline-block;
padding: 0.25rem 0.5rem;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
background-color: {theme['accent']};
color: {theme['text']};
}}
</style>
"""
st.markdown(css, unsafe_allow_html=True)
def create_card(content: str, key: str = None) -> None:
"""
Create a styled card container.
Args:
content: HTML content to display in card
key: Optional unique key for the card
"""
st.markdown(
f'<div class="message-card">{content}</div>',
unsafe_allow_html=True
)
def create_badge(text: str, color: str = None) -> str:
"""
Create a styled badge element.
Args:
text: Badge text
color: Optional custom color
Returns:
str: HTML for badge
"""
style = f'background-color: {color};' if color else ''
return f'<span class="badge" style="{style}">{text}</span>'