Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions widgets/themes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"themes": {
"gruvbox": {
"background": "#282828",
"foreground": "#fbf1c7",
"primary": "#85A598",
"secondary": "#A89A85",
"accent": "#fabd2f",
"surface": "#3c3836",
"panel": "#504945"
},
"dracula": {
"background": "#282a36",
"foreground": "#f8f8f2",
"primary": "#bd93f9",
"secondary": "#6272a4",
"accent": "#ff79c6",
"surface": "#44475a",
"panel": "#6272a4"
},
"nord": {
"background": "#2e3440",
"foreground": "#d8dee9",
"primary": "#88c0d0",
"secondary": "#5e81ac",
"accent": "#81a1c1",
"surface": "#3b4252",
"panel": "#434c5e"
},
"solarized-dark": {
"background": "#002b36",
"foreground": "#839496",
"primary": "#268bd2",
"secondary": "#586e75",
"accent": "#b58900",
"surface": "#073642",
"panel": "#586e75"
},
"monokai": {
"background": "#272822",
"foreground": "#f8f8f2",
"primary": "#66d9ef",
"secondary": "#75715e",
"accent": "#fd971f",
"surface": "#383830",
"panel": "#49483e"
}
}
}
77 changes: 77 additions & 0 deletions widgets/widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""
An App to show the current time with theme support.
"""

import json
import sys
from datetime import datetime
from pathlib import Path

from textual.app import App, ComposeResult
from textual.widgets import Digits


def load_themes():
"""Load themes from themes.json file."""
themes_file = Path(__file__).parent / "themes.json"
with open(themes_file) as f:
data = json.load(f)
return data["themes"]


def get_theme_css(theme_name: str) -> str:
"""Generate CSS for a specific theme."""
themes = load_themes()
if theme_name not in themes:
available = ", ".join(themes.keys())
raise ValueError(f"Theme '{theme_name}' not found. Available: {available}")

theme = themes[theme_name]
return f"""
Screen {{
align: center middle;
background: {theme['background']};
}}
Digits {{
width: auto;
color: {theme['foreground']};
}}
"""


class ClockApp(App):
CSS = """
Screen { align: center middle; background: #282828; }
Digits { width: auto; color: #fbf1c7; }
"""

def __init__(self, theme_name: str = "gruvbox", **kwargs):
self.theme_name = theme_name
# Override CSS with theme
ClockApp.CSS = get_theme_css(theme_name)
super().__init__(**kwargs)

def compose(self) -> ComposeResult:
yield Digits("")

def on_ready(self) -> None:
self.update_clock()
self.set_interval(1, self.update_clock)

def update_clock(self) -> None:
clock = datetime.now().time()
self.query_one(Digits).update(f"{clock:%T}")


if __name__ == "__main__":
# Parse command line arguments for theme selection
theme = "gruvbox"
if len(sys.argv) > 1:
theme = sys.argv[1]

try:
app = ClockApp(theme_name=theme)
app.run()
except ValueError as e:
print(f"Error: {e}")
sys.exit(1)