Source code for iskg.themes

"""Named theme definitions for ISKG.

Each theme is a dict of CSS custom property overrides applied on top of
the default IFAZ style sheet (``iskg.theme.IFAZ_CSS``).

Available themes: ifaz, desert, infinity, cyberdusk, light, dracula, nord,
gruvbox, monokai, catppuccin.

Usage::

    from iskg.themes import THEMES, available_themes, theme_js

    # List available themes
    available_themes()  # -> ["ifaz", "desert", ...]

    # Apply theme at runtime
    app.set_theme("dracula")

    # Or get JS to apply manually
    js = theme_js("nord")
    app.execute_js(js)
"""

from __future__ import annotations

THEMES: dict[str, dict[str, str]] = {
    "ifaz": {
        "--bg-primary": "#070b10",
        "--bg-panel": "#0c111a",
        "--bg-panel-alt": "#111822",
        "--bg-panel-hi": "#16202e",
        "--border": "#1a2636",
        "--border-light": "#28364a",
        "--green": "#4ade80",
        "--green-dim": "#0f2e1a",
        "--amber": "#f59e0b",
        "--amber-dim": "#2e2008",
        "--red": "#ef4444",
        "--red-dim": "#2e0e0e",
        "--cyan": "#22d3ee",
        "--cyan-dim": "#0a2030",
        "--text": "#c8d6e5",
        "--text-dim": "#4a5a6a",
        "--text-green": "#7ec850",
        "--progress-from": "#0f2e1a",
        "--progress-to": "#2e2008",
    },
    "desert": {
        "--bg-primary": "#1a1410",
        "--bg-panel": "#221c16",
        "--bg-panel-alt": "#2a241e",
        "--bg-panel-hi": "#342e26",
        "--border": "#3a342c",
        "--border-light": "#4a443a",
        "--green": "#a3b18a",
        "--green-dim": "#1a2214",
        "--amber": "#d4a373",
        "--amber-dim": "#2a2016",
        "--red": "#e07a5f",
        "--red-dim": "#2e1810",
        "--cyan": "#8ecae6",
        "--cyan-dim": "#10202a",
        "--text": "#d4c9b8",
        "--text-dim": "#6a5f52",
        "--text-green": "#a3b18a",
        "--progress-from": "#1a2214",
        "--progress-to": "#2a2016",
    },
    "infinity": {
        "--bg-primary": "#050510",
        "--bg-panel": "#0a0a1a",
        "--bg-panel-alt": "#101025",
        "--bg-panel-hi": "#181838",
        "--border": "#1a1a3a",
        "--border-light": "#282858",
        "--green": "#00ffc8",
        "--green-dim": "#002a20",
        "--amber": "#ff6600",
        "--amber-dim": "#2a1000",
        "--red": "#ff3355",
        "--red-dim": "#2e0008",
        "--cyan": "#00d4ff",
        "--cyan-dim": "#002a38",
        "--text": "#e0e0ff",
        "--text-dim": "#6060a0",
        "--text-green": "#00ffc8",
        "--progress-from": "#002a20",
        "--progress-to": "#002a38",
    },
    "cyberdusk": {
        "--bg-primary": "#080c1a",
        "--bg-panel": "#0e1428",
        "--bg-panel-alt": "#141c34",
        "--bg-panel-hi": "#1c2640",
        "--border": "#222e4a",
        "--border-light": "#2e3c5c",
        "--green": "#4ade80",
        "--green-dim": "#0a1e12",
        "--amber": "#fbbf24",
        "--amber-dim": "#1e1a06",
        "--red": "#ef4444",
        "--red-dim": "#2a0a0a",
        "--cyan": "#38bdf8",
        "--cyan-dim": "#0a2035",
        "--text": "#c8d6e5",
        "--text-dim": "#4a5a7a",
        "--text-green": "#60a5fa",
        "--progress-from": "#0a2035",
        "--progress-to": "#1a1a3a",
    },
    "light": {
        "--bg-primary": "#e8eaed",
        "--bg-panel": "#f2f3f5",
        "--bg-panel-alt": "#e2e4e8",
        "--bg-panel-hi": "#d5d7db",
        "--border": "#b0b3b8",
        "--border-light": "#c4c7cc",
        "--green": "#2e7d32",
        "--green-dim": "#e8f5e9",
        "--amber": "#e65100",
        "--amber-dim": "#fff3e0",
        "--red": "#c62828",
        "--red-dim": "#ffebee",
        "--cyan": "#00838f",
        "--cyan-dim": "#e0f7fa",
        "--text": "#202124",
        "--text-dim": "#5f6368",
        "--text-green": "#2e7d32",
        "--progress-from": "#e8f5e9",
        "--progress-to": "#fff3e0",
    },
    "dracula": {
        "--bg-primary": "#282a36",
        "--bg-panel": "#2d2f3e",
        "--bg-panel-alt": "#363848",
        "--bg-panel-hi": "#404254",
        "--border": "#44475a",
        "--border-light": "#525466",
        "--green": "#50fa7b",
        "--green-dim": "#1a2e1a",
        "--amber": "#f1fa8c",
        "--amber-dim": "#2a2a10",
        "--red": "#ff5555",
        "--red-dim": "#2e0e0e",
        "--cyan": "#8be9fd",
        "--cyan-dim": "#0a2a32",
        "--text": "#f8f8f2",
        "--text-dim": "#6a6a8a",
        "--text-green": "#50fa7b",
        "--progress-from": "#1a2e1a",
        "--progress-to": "#2a2a10",
    },
    "nord": {
        "--bg-primary": "#2e3440",
        "--bg-panel": "#353b4a",
        "--bg-panel-alt": "#3b4252",
        "--bg-panel-hi": "#434c5e",
        "--border": "#4c566a",
        "--border-light": "#5e687c",
        "--green": "#a3be8c",
        "--green-dim": "#1a2416",
        "--amber": "#ebcb8b",
        "--amber-dim": "#2a2416",
        "--red": "#bf616a",
        "--red-dim": "#2a1014",
        "--cyan": "#88c0d0",
        "--cyan-dim": "#14242a",
        "--text": "#e5e9f0",
        "--text-dim": "#6a7a8a",
        "--text-green": "#a3be8c",
        "--progress-from": "#1a2416",
        "--progress-to": "#2a2416",
    },
    "gruvbox": {
        "--bg-primary": "#1d2021",
        "--bg-panel": "#252829",
        "--bg-panel-alt": "#2c2f30",
        "--bg-panel-hi": "#333638",
        "--border": "#3c3f41",
        "--border-light": "#4a4d4f",
        "--green": "#98971a",
        "--green-dim": "#1a1c08",
        "--amber": "#d79921",
        "--amber-dim": "#2a2008",
        "--red": "#cc241d",
        "--red-dim": "#2a0a08",
        "--cyan": "#689d6a",
        "--cyan-dim": "#0e1e10",
        "--text": "#ebdbb2",
        "--text-dim": "#6a5e4a",
        "--text-green": "#98971a",
        "--progress-from": "#1a1c08",
        "--progress-to": "#2a2008",
    },
    "monokai": {
        "--bg-primary": "#1e1f1c",
        "--bg-panel": "#242520",
        "--bg-panel-alt": "#2a2b26",
        "--bg-panel-hi": "#32332e",
        "--border": "#3a3b36",
        "--border-light": "#484946",
        "--green": "#a6e22e",
        "--green-dim": "#182a08",
        "--amber": "#e6db74",
        "--amber-dim": "#2a2814",
        "--red": "#f92672",
        "--red-dim": "#2e0818",
        "--cyan": "#66d9ef",
        "--cyan-dim": "#0a2832",
        "--text": "#f8f8f2",
        "--text-dim": "#6a6a5a",
        "--text-green": "#a6e22e",
        "--progress-from": "#182a08",
        "--progress-to": "#2a2814",
    },
    "catppuccin": {
        "--bg-primary": "#1e1e2e",
        "--bg-panel": "#252538",
        "--bg-panel-alt": "#2b2b40",
        "--bg-panel-hi": "#32324a",
        "--border": "#3a3a52",
        "--border-light": "#484862",
        "--green": "#a6e3a1",
        "--green-dim": "#1a2a18",
        "--amber": "#f9e2af",
        "--amber-dim": "#2a2618",
        "--red": "#f38ba8",
        "--red-dim": "#2e101e",
        "--cyan": "#89dceb",
        "--cyan-dim": "#122a2e",
        "--text": "#cdd6f4",
        "--text-dim": "#5a5a7a",
        "--text-green": "#a6e3a1",
        "--progress-from": "#1a2a18",
        "--progress-to": "#2a2618",
    },
}


[docs] def resolve_theme(name: str) -> dict[str, str]: """Return the theme dict for *name*, falling back to ``"ifaz"``.""" return THEMES.get(name, THEMES["ifaz"])
[docs] def theme_js(name: str) -> str: """Return a JavaScript snippet that applies the named theme in the browser. Call ``execute_js()`` on the application window to apply:: app.execute_js(theme_js("cold")) """ overrides = resolve_theme(name) pairs = ",".join(f'"{k}":"{v}"' for k, v in overrides.items()) return f"iskg_apply_theme({{{pairs}}});"
[docs] def theme_css(name: str) -> str: """Return a CSS ``:root`` block for the named theme (for initial render).""" overrides = resolve_theme(name) rules = "".join(f" {k}: {v};\n" for k, v in overrides.items()) return f":root {{\n{rules}}}\n"
[docs] def available_themes() -> list[str]: """Return the list of registered theme names.""" return list(THEMES.keys())
THEME_VARS: list[str] = [ "--bg-primary", "--bg-panel", "--bg-panel-alt", "--bg-panel-hi", "--border", "--border-light", "--green", "--green-dim", "--amber", "--amber-dim", "--red", "--red-dim", "--cyan", "--cyan-dim", "--text", "--text-dim", "--text-green", "--progress-from", "--progress-to", ]