152 lines
4.9 KiB
Python
152 lines
4.9 KiB
Python
"""
|
|
web/themes.py — CSS variable themes for oAI-Web.
|
|
|
|
Each theme is a set of CSS variable overrides injected into base.html as a
|
|
<style> block, overriding the :root defaults in style.css.
|
|
Non-colour tokens (--radius, --font, --mono) are not overridden so they
|
|
inherit from style.css.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
DEFAULT_THEME = "dark"
|
|
|
|
# Each entry: id → {label, preview (bg, accent), vars}
|
|
THEMES: dict[str, dict] = {
|
|
"dark": {
|
|
"label": "Dark",
|
|
"preview": {"bg": "#1a1d27", "accent": "#6c8ef5"},
|
|
"vars": {
|
|
"--bg": "#0f1117",
|
|
"--bg2": "#1a1d27",
|
|
"--bg3": "#22263a",
|
|
"--border": "#2e3249",
|
|
"--text": "#e2e4ef",
|
|
"--text-dim": "#7b82a8",
|
|
"--accent": "#6c8ef5",
|
|
"--accent-dim": "#3d5099",
|
|
"--green": "#4caf7d",
|
|
"--red": "#e05252",
|
|
"--yellow": "#e0a632",
|
|
},
|
|
},
|
|
"darker": {
|
|
"label": "Darker",
|
|
"preview": {"bg": "#111111", "accent": "#6c8ef5"},
|
|
"vars": {
|
|
"--bg": "#000000",
|
|
"--bg2": "#0d0d0d",
|
|
"--bg3": "#1a1a1a",
|
|
"--border": "#2a2a2a",
|
|
"--text": "#e2e4ef",
|
|
"--text-dim": "#6b7280",
|
|
"--accent": "#6c8ef5",
|
|
"--accent-dim": "#3d5099",
|
|
"--green": "#4caf7d",
|
|
"--red": "#e05252",
|
|
"--yellow": "#e0a632",
|
|
},
|
|
},
|
|
"light": {
|
|
"label": "Light",
|
|
"preview": {"bg": "#ffffff", "accent": "#4b6ef5"},
|
|
"vars": {
|
|
"--bg": "#f5f6fa",
|
|
"--bg2": "#ffffff",
|
|
"--bg3": "#eef0f7",
|
|
"--border": "#d1d5e8",
|
|
"--text": "#1a1d2e",
|
|
"--text-dim": "#6b7280",
|
|
"--accent": "#4b6ef5",
|
|
"--accent-dim": "#a3b4fa",
|
|
"--green": "#2e8a57",
|
|
"--red": "#c0392b",
|
|
"--yellow": "#b7791f",
|
|
},
|
|
},
|
|
"nord": {
|
|
"label": "Nord",
|
|
"preview": {"bg": "#3b4252", "accent": "#88c0d0"},
|
|
"vars": {
|
|
"--bg": "#2e3440",
|
|
"--bg2": "#3b4252",
|
|
"--bg3": "#434c5e",
|
|
"--border": "#4c566a",
|
|
"--text": "#eceff4",
|
|
"--text-dim": "#8a97b0",
|
|
"--accent": "#88c0d0",
|
|
"--accent-dim": "#4a7a8a",
|
|
"--green": "#a3be8c",
|
|
"--red": "#bf616a",
|
|
"--yellow": "#ebcb8b",
|
|
},
|
|
},
|
|
"solarized": {
|
|
"label": "Solarized Dark",
|
|
"preview": {"bg": "#073642", "accent": "#268bd2"},
|
|
"vars": {
|
|
"--bg": "#002b36",
|
|
"--bg2": "#073642",
|
|
"--bg3": "#0d4454",
|
|
"--border": "#1a5566",
|
|
"--text": "#839496",
|
|
"--text-dim": "#586e75",
|
|
"--accent": "#268bd2",
|
|
"--accent-dim": "#1a5c8c",
|
|
"--green": "#859900",
|
|
"--red": "#dc322f",
|
|
"--yellow": "#b58900",
|
|
},
|
|
},
|
|
"gruvbox": {
|
|
"label": "Gruvbox",
|
|
"preview": {"bg": "#3c3836", "accent": "#d79921"},
|
|
"vars": {
|
|
"--bg": "#282828",
|
|
"--bg2": "#3c3836",
|
|
"--bg3": "#504945",
|
|
"--border": "#665c54",
|
|
"--text": "#ebdbb2",
|
|
"--text-dim": "#928374",
|
|
"--accent": "#458588",
|
|
"--accent-dim": "#2d5b5e",
|
|
"--green": "#98971a",
|
|
"--red": "#cc241d",
|
|
"--yellow": "#d79921",
|
|
},
|
|
},
|
|
"catppuccin": {
|
|
"label": "Catppuccin",
|
|
"preview": {"bg": "#1e1e2e", "accent": "#cba6f7"},
|
|
"vars": {
|
|
"--bg": "#1e1e2e",
|
|
"--bg2": "#181825",
|
|
"--bg3": "#313244",
|
|
"--border": "#45475a",
|
|
"--text": "#cdd6f4",
|
|
"--text-dim": "#6c7086",
|
|
"--accent": "#cba6f7",
|
|
"--accent-dim": "#6e4d9e",
|
|
"--green": "#a6e3a1",
|
|
"--red": "#f38ba8",
|
|
"--yellow": "#f9e2af",
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
def get_theme_css(theme_id: str) -> str:
|
|
"""Return a CSS :root override block for the given theme, or empty string for the default."""
|
|
if theme_id == DEFAULT_THEME or theme_id not in THEMES:
|
|
return ""
|
|
vars = THEMES[theme_id]["vars"]
|
|
lines = "\n".join(f" {k}: {v};" for k, v in vars.items())
|
|
return f":root {{\n{lines}\n}}"
|
|
|
|
|
|
def theme_list() -> list[dict]:
|
|
"""Return theme metadata for the UI picker (no CSS vars)."""
|
|
return [
|
|
{"id": tid, "label": t["label"], "preview": t["preview"]}
|
|
for tid, t in THEMES.items()
|
|
]
|