Skip to content

Commit

Permalink
themes plumbing
Browse files Browse the repository at this point in the history
  • Loading branch information
darrenburns committed Sep 10, 2024
1 parent f1cabd4 commit 518028c
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 3 deletions.
37 changes: 35 additions & 2 deletions elia_chat/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from elia_chat.screens.chat_screen import ChatScreen
from elia_chat.screens.help_screen import HelpScreen
from elia_chat.screens.home_screen import HomeScreen
from elia_chat.themes import BUILTIN_THEMES, Theme, load_user_themes

if TYPE_CHECKING:
from litellm.types.completion import (
Expand All @@ -33,7 +34,6 @@ class Elia(App[None]):
]

def __init__(self, config: LaunchConfig, startup_prompt: str = ""):
super().__init__()
self.launch_config = config
launch_config.set(config)
self._runtime_config = RuntimeConfig(
Expand All @@ -53,7 +53,14 @@ def __init__(self, config: LaunchConfig, startup_prompt: str = ""):
put users into the chat window, rather than going to the home screen.
"""

theme: Reactive[str] = reactive("elia", init=False)
available_themes: dict[str, Theme] = {"galaxy": BUILTIN_THEMES["galaxy"]}
available_themes |= load_user_themes()

self.themes: dict[str, Theme] = available_themes

super().__init__()

theme: Reactive[str | None] = reactive(None, init=False)

@property
def runtime_config(self) -> RuntimeConfig:
Expand All @@ -66,6 +73,7 @@ def runtime_config(self, new_runtime_config: RuntimeConfig) -> None:

async def on_mount(self) -> None:
await self.push_screen(HomeScreen(self.runtime_config_signal))
self.theme = self.launch_config.theme
if self.startup_prompt:
await self.launch_chat(
prompt=self.startup_prompt,
Expand Down Expand Up @@ -109,6 +117,31 @@ async def action_help(self) -> None:
else:
await self.push_screen(HelpScreen())

def get_css_variables(self) -> dict[str, str]:
if self.theme:
theme = self.themes.get(self.theme)
if theme:
color_system = theme.to_color_system().generate()
else:
color_system = {}
else:
color_system = {}

return {**super().get_css_variables(), **color_system}

def watch_theme(self, theme: str | None) -> None:
self.refresh_css(animate=False)
self.screen._update_styles()
if theme:
print(self.theme_object)

@property
def theme_object(self) -> Theme | None:
try:
return self.themes[self.theme]
except KeyError:
return None


if __name__ == "__main__":
app = Elia(LaunchConfig())
Expand Down
2 changes: 1 addition & 1 deletion elia_chat/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ class LaunchConfig(BaseModel):
builtin_models: list[EliaChatModel] = Field(
default_factory=get_builtin_models, init=False
)
theme: str = Field(default="elia")
theme: str = Field(default="galaxy")

@property
def all_models(self) -> list[EliaChatModel]:
Expand Down
151 changes: 151 additions & 0 deletions elia_chat/themes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pydantic import BaseModel, Field
from textual.design import ColorSystem
import yaml

from elia_chat.locations import theme_directory
Expand All @@ -17,6 +18,20 @@ class Theme(BaseModel):
accent: str | None = None
dark: bool = True

def to_color_system(self) -> ColorSystem:
"""Convert this theme to a ColorSystem."""
return ColorSystem(
**self.model_dump(
exclude={
"text_area",
"syntax",
"variable",
"url",
"method",
}
)
)


def load_user_themes() -> dict[str, Theme]:
"""Load user themes from "~/.config/elia/themes".
Expand All @@ -37,3 +52,139 @@ def load_user_themes() -> dict[str, Theme]:
f"Invalid theme file {path}. A `name` is required."
)
return themes


BUILTIN_THEMES: dict[str, Theme] = {
"posting": Theme(
name="posting",
primary="#004578",
secondary="#0178D4",
warning="#ffa62b",
error="#ba3c5b",
success="#4EBF71",
accent="#ffa62b",
dark=True,
syntax="posting",
),
"monokai": Theme(
name="monokai",
primary="#F92672", # Pink
secondary="#66D9EF", # Light Blue
warning="#FD971F", # Orange
error="#F92672", # Pink (same as primary for consistency)
success="#A6E22E", # Green
accent="#AE81FF", # Purple
background="#272822", # Dark gray-green
surface="#3E3D32", # Slightly lighter gray-green
panel="#3E3D32", # Same as surface for consistency
dark=True,
syntax="monokai",
),
"solarized-light": Theme(
name="solarized-light",
primary="#268bd2",
secondary="#2aa198",
warning="#cb4b16",
error="#dc322f",
success="#859900",
accent="#6c71c4",
background="#fdf6e3",
surface="#eee8d5",
panel="#eee8d5",
syntax="github_light",
),
"nautilus": Theme(
name="nautilus",
primary="#0077BE", # Ocean Blue
secondary="#20B2AA", # Light Sea Green
warning="#FFD700", # Gold (like sunlight on water)
error="#FF6347", # Tomato (like a warning buoy)
success="#32CD32", # Lime Green (like seaweed)
accent="#FF8C00", # Dark Orange (like a sunset over water)
dark=True,
background="#001F3F", # Dark Blue (deep ocean)
surface="#003366", # Navy Blue (shallower water)
panel="#005A8C", # Steel Blue (water surface)
syntax="posting",
),
"galaxy": Theme(
name="galaxy",
primary="#8A2BE2", # Improved Deep Magenta (Blueviolet)
secondary="#a684e8",
warning="#FFD700", # Gold, more visible than orange
error="#FF4500", # OrangeRed, vibrant but less harsh than pure red
success="#00FA9A", # Medium Spring Green, kept for vibrancy
accent="#FF69B4", # Hot Pink, for a pop of color
dark=True,
background="#0F0F1F", # Very Dark Blue, almost black
surface="#1E1E3F", # Dark Blue-Purple
panel="#2D2B55", # Slightly Lighter Blue-Purple
syntax="monokai",
),
"nebula": Theme(
name="nebula",
primary="#4169E1", # Royal Blue, more vibrant than Midnight Blue
secondary="#9400D3", # Dark Violet, more vibrant than Indigo Dye
warning="#FFD700", # Kept Gold for warnings
error="#FF1493", # Deep Pink, more nebula-like than Crimson
success="#00FF7F", # Spring Green, slightly more vibrant
accent="#FF00FF", # Magenta, for a true neon accent
dark=True,
background="#0A0A23", # Dark Navy, closer to a night sky
surface="#1C1C3C", # Dark Blue-Purple
panel="#2E2E5E", # Slightly Lighter Blue-Purple
syntax="dracula",
),
"alpine": Theme(
name="alpine",
primary="#4A90E2", # Clear Sky Blue
secondary="#81A1C1", # Misty Blue
warning="#EBCB8B", # Soft Sunlight
error="#BF616A", # Muted Red
success="#A3BE8C", # Alpine Meadow Green
accent="#5E81AC", # Mountain Lake Blue
dark=True,
background="#2E3440", # Dark Slate Grey
surface="#3B4252", # Darker Blue-Grey
panel="#434C5E", # Lighter Blue-Grey
),
"cobalt": Theme(
name="cobalt",
primary="#334D5C", # Deep Cobalt Blue
secondary="#4878A6", # Slate Blue
warning="#FFAA22", # Amber, suitable for warnings related to primary
error="#E63946", # Red, universally recognized for errors
success="#4CAF50", # Green, commonly used for success indication
accent="#D94E64", # Candy Apple Red
dark=True,
surface="#27343B", # Dark Lead
panel="#2D3E46", # Storm Gray
background="#1F262A", # Charcoal
),
"twilight": Theme(
name="twilight",
primary="#367588",
secondary="#5F9EA0",
warning="#FFD700",
error="#FF6347",
success="#00FA9A",
accent="#FF7F50",
dark=True,
background="#191970",
surface="#3B3B6D",
panel="#4C516D",
),
"hacker": Theme(
name="hacker",
primary="#00FF00", # Bright Green (Lime)
secondary="#32CD32", # Lime Green
warning="#ADFF2F", # Green Yellow
error="#FF4500", # Orange Red (for contrast)
success="#00FA9A", # Medium Spring Green
accent="#39FF14", # Neon Green
dark=True,
background="#0D0D0D", # Almost Black
surface="#1A1A1A", # Very Dark Gray
panel="#2A2A2A", # Dark Gray
),
}

0 comments on commit 518028c

Please sign in to comment.