import streamlit as st CHART_HEIGHT = 520 # ── DESIGN SYSTEM TOKENS — aligned with tijartek_dashboard_html.html ── COLORS = { # Core palette (matches HTML :root vars) "primary": "#00c9b1", # --teal "primary_dark": "#009985", "accent": "#0085ff", # --blue "accent2": "#ff4d6d", # --red "accent3": "#f5c842", # --gold "accent4": "#9b6dff", # --purple "success": "#00e096", # --green "warning": "#f5c842", # --gold "danger": "#ff4d6d", # --red # Backgrounds (matches HTML) "bg_dark": "#030d1a", # --bg "bg_card": "#0d2540", # --card "bg_card2": "#0f2d4a", # --card2 "bg2": "#061526", # --bg2 "bg3": "#0a1f35", # --bg3 # Text "text_primary": "#e8f4ff", # --text "text_muted": "#7aadcc", # --text2 "text_dim": "#3d6880", # --text3 # Border "border": "rgba(0,201,177,0.12)", # --border } PLOTLY_PALETTE = [ "#00c9b1", # teal "#0085ff", # blue "#f5c842", # gold "#ff4d6d", # red "#00e096", # green "#9b6dff", # purple "#38a8ff", # blue2 "#00e5cc", # teal2 ] CHART_LAYOUT = dict( paper_bgcolor="rgba(0,0,0,0)", plot_bgcolor="rgba(0,0,0,0)", font=dict(family="'DM Sans', sans-serif", color="#7aadcc", size=12), title_font=dict(family="'Syne', sans-serif", color="#e8f4ff", size=15), legend=dict( bgcolor="rgba(13,37,64,0.92)", bordercolor="rgba(0,201,177,0.18)", borderwidth=1, font=dict(color="#7aadcc", size=11), ), xaxis=dict( gridcolor="rgba(0,201,177,0.06)", linecolor="rgba(0,201,177,0.12)", tickfont=dict(color="#3d6880"), ), yaxis=dict( gridcolor="rgba(0,201,177,0.06)", linecolor="rgba(0,201,177,0.12)", tickfont=dict(color="#3d6880"), ), margin=dict(l=16, r=16, t=56, b=16), hoverlabel=dict( bgcolor="#0d2540", bordercolor="rgba(0,201,177,0.35)", font=dict(color="#e8f4ff", size=12), ), ) GLOBAL_CSS = """ """ def inject_theme(): """Inject the global CSS design system (aligned with HTML dashboard).""" st.markdown(GLOBAL_CSS, unsafe_allow_html=True) def section_title(title: str, subtitle: str = ""): """Styled section header matching HTML .page-title / .section-title style.""" html = f"""

{title}

""" if subtitle: html += f'

{subtitle}

' st.markdown(html, unsafe_allow_html=True) def render_kpi_row(metrics: list, num_cols: int = 4): """ Render a row of KPI metric cards. Each metric dict may include: label, value, delta, color (teal/blue/gold/red/green/purple). The color controls the top accent bar and value color via CSS class. """ cols = st.columns(num_cols) for i, m in enumerate(metrics): with cols[i % num_cols]: color_cls = m.get("color", "") # Inject a wrapper div with the appropriate kpi color class if color_cls and color_cls != "teal": st.markdown( f'', unsafe_allow_html=True, ) st.metric( label=m.get("label", "—"), value=m.get("value", "—"), delta=m.get("delta"), ) st.markdown("
", unsafe_allow_html=True) def filter_bar(label: str = "Filters"): """Styled container for filter rows.""" return st.container() def insight_badge(text: str): """Render a small teal pill badge — matches .section-tag in HTML.""" st.markdown(f'{text}', unsafe_allow_html=True) def empty_state(message: str, icon: str = "📭"): """Placeholder card for missing data.""" st.markdown( f"""
{icon}

{message}

""", unsafe_allow_html=True, ) def progress_row(label: str, value_label: str, pct: float, color: str = ""): """ Render a labeled progress bar row — matches HTML progress-bar pattern. color: '', 'gold', 'red', 'green', 'purple' pct: 0–100 """ fill_class = f"tj-progress-fill {color}".strip() st.markdown( f"""
{label} {value_label}
""", unsafe_allow_html=True, ) def alert_row(message: str, level: str = "error"): """ Render a styled alert item — matches HTML .alert-item. level: 'error' (red), 'warn' (gold), 'info' (blue), 'ok' (green) """ cls_map = {"error": "", "warn": "warn", "info": "info", "ok": "ok"} icon_map = {"error": "⚠️", "warn": "⚡", "info": "ℹ️", "ok": "✅"} cls = cls_map.get(level, "") icon = icon_map.get(level, "•") st.markdown( f'
' f'{icon}' f'{message}' f'
', unsafe_allow_html=True, ) def rank_table_html(rows: list, headers: list) -> str: """ Build an HTML rank table string (use with st.markdown unsafe_allow_html=True). rows: list of lists; first column treated as rank number (1-3 get gold/silver/bronze badges). headers: list of column header strings. """ th = "".join(f"{h}" for h in headers) tbody = "" for i, row in enumerate(rows): tds = "" for j, cell in enumerate(row): if j == 0: if i == 0: badge_cls = "gold" elif i == 1: badge_cls = "silver" elif i == 2: badge_cls = "bronze" else: badge_cls = "" tds += f'{cell}' else: tds += f"{cell}" tbody += f"{tds}" return f'{th}{tbody}
'