Source code for ooai_llm.tui.themes

"""Theme palettes for the optional Textual explorer.

Purpose:
    Keep visual choices out of the TUI event wiring so the app can offer
    multiple usable terminal looks without becoming a wall of CSS.

Design:
    Themes are intentionally simple named palettes. They avoid third-party
    theme packages for now because Textual CSS is enough for the current app
    and the TUI extra should stay lightweight.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Literal

[docs] TUIThemeName = Literal["paper", "slate", "mono", "forest"]
[docs] TUI_THEME_CHOICES: tuple[TUIThemeName, ...] = ("paper", "slate", "mono", "forest")
@dataclass(frozen=True)
[docs] class TUITheme: """Named color palette used to render the Textual explorer."""
[docs] screen_bg: str
[docs] screen_fg: str
[docs] header_bg: str
[docs] header_fg: str
[docs] footer_bg: str
[docs] footer_fg: str
[docs] card_bg: str
[docs] card_border: str
[docs] table_bg: str
[docs] table_border: str
[docs] detail_bg: str
[docs] detail_border: str
[docs] focus: str
[docs] active_bg: str
[docs] active_fg: str
[docs] summary: str
[docs] status: str
[docs] notes: str
[docs] TUI_THEMES: dict[TUIThemeName, TUITheme] = { "paper": TUITheme( screen_bg="#f7f1df", screen_fg="#1d241f", header_bg="#303b35", header_fg="#fff7dc", footer_bg="#e2d7bd", footer_fg="#29322d", card_bg="#fff9e8", card_border="#9b8b63", table_bg="#fffdf5", table_border="#9c9078", detail_bg="#fff7df", detail_border="#8d805f", focus="#b65c32", active_bg="#24352f", active_fg="#fff7dc", summary="#9a6a28", status="#527a57", notes="#a9563f", ), "slate": TUITheme( screen_bg="#0d1117", screen_fg="#e6edf3", header_bg="#161b22", header_fg="#f0f6fc", footer_bg="#111820", footer_fg="#c9d1d9", card_bg="#111820", card_border="#46515f", table_bg="#0b1016", table_border="#384553", detail_bg="#121923", detail_border="#536273", focus="#f0b45b", active_bg="#f0b45b", active_fg="#0d1117", summary="#f0b45b", status="#7ccf8d", notes="#76b7e5", ), "mono": TUITheme( screen_bg="#111111", screen_fg="#eeeeee", header_bg="#202020", header_fg="#ffffff", footer_bg="#181818", footer_fg="#cfcfcf", card_bg="#171717", card_border="#707070", table_bg="#101010", table_border="#5c5c5c", detail_bg="#191919", detail_border="#7a7a7a", focus="#ffffff", active_bg="#eeeeee", active_fg="#111111", summary="#d7d7d7", status="#bbbbbb", notes="#999999", ), "forest": TUITheme( screen_bg="#10150f", screen_fg="#edf1dc", header_bg="#253224", header_fg="#f5efd0", footer_bg="#182019", footer_fg="#cfd8b8", card_bg="#151d14", card_border="#5f6f45", table_bg="#0f140f", table_border="#455437", detail_bg="#171c16", detail_border="#6f7753", focus="#f0c36a", active_bg="#f0c36a", active_fg="#10150f", summary="#f0c36a", status="#9cc27d", notes="#d58b62", ), }
[docs] def tui_theme_css(theme: TUIThemeName = "paper") -> str: """Return Textual CSS for a named explorer theme.""" palette = TUI_THEMES[theme] return f""" Screen {{ background: {palette.screen_bg}; color: {palette.screen_fg}; }} Header {{ background: {palette.header_bg}; color: {palette.header_fg}; }} Footer {{ background: {palette.footer_bg}; color: {palette.footer_fg}; }} #layout {{ height: 100%; }} #dashboard {{ height: auto; min-height: 7; padding: 1 1 0 1; }} .card {{ width: 1fr; min-height: 6; margin: 0 1 0 0; padding: 1 2; border: round {palette.card_border}; background: {palette.card_bg}; color: {palette.screen_fg}; }} #summary-card {{ border-title-color: {palette.summary}; }} #status-card {{ border-title-color: {palette.status}; }} #notes-card {{ border-title-color: {palette.notes}; }} #controls {{ height: auto; min-height: 4; padding: 0 1 1 1; }} #nav {{ height: auto; min-height: 3; padding: 0 1 1 1; }} .nav-button {{ margin-right: 1; min-width: 13; }} .nav-button.active {{ background: {palette.active_bg}; color: {palette.active_fg}; text-style: bold; }} #search {{ width: 2fr; margin-right: 1; }} #provider-filter {{ width: 28; margin-right: 1; }} #view-select {{ width: 22; margin-right: 1; }} #refresh-button {{ width: 15; }} ContentSwitcher {{ height: 1fr; }} .pane {{ height: 1fr; padding: 1; }} .table-workspace {{ height: 1fr; }} DataTable {{ width: 2fr; height: 1fr; border: round {palette.table_border}; background: {palette.table_bg}; color: {palette.screen_fg}; }} DataTable:focus {{ border: heavy {palette.focus}; }} .detail {{ width: 1fr; height: 1fr; margin-left: 1; padding: 1 2; border: round {palette.detail_border}; background: {palette.detail_bg}; color: {palette.screen_fg}; }} #home-markdown, #profile-markdown {{ height: 1fr; padding: 1 2; border: round {palette.card_border}; background: {palette.card_bg}; }} """