a96c1a52f4
Port all web CSS token themes to TUI via shared vocabulary (accent, dim, muted, ok, todo, event, remind, danger). Styles rebuild from active theme on switch. Press T to cycle, persists to ~/.nib/theme. Glamour markdown renderer respects light/dark per theme.
91 lines
3.3 KiB
Go
91 lines
3.3 KiB
Go
package tui
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
type Theme struct {
|
|
Name string
|
|
Dark bool
|
|
Accent string
|
|
Dim string
|
|
Muted string
|
|
Ok string
|
|
Todo string
|
|
Event string
|
|
Remind string
|
|
Danger string
|
|
}
|
|
|
|
var themes = []Theme{
|
|
{Name: "dark", Dark: true, Accent: "#c8942a", Dim: "#504840", Muted: "#8c8070", Ok: "#7aab72", Todo: "#d4a84b", Event: "#6898c8", Remind: "#c8784a", Danger: "#b85858"},
|
|
{Name: "tinycard", Dark: true, Accent: "#ad8ee6", Dim: "#555a6a", Muted: "#8b90a0", Ok: "#4ade80", Todo: "#fbbf24", Event: "#22d3ee", Remind: "#e8845a", Danger: "#ef4444"},
|
|
{Name: "catppuccin", Dark: true, Accent: "#cba6f7", Dim: "#6c7086", Muted: "#a6adc8", Ok: "#a6e3a1", Todo: "#f9e2af", Event: "#89b4fa", Remind: "#fab387", Danger: "#f38ba8"},
|
|
{Name: "nord", Dark: true, Accent: "#88c0d0", Dim: "#4c566a", Muted: "#d8dee9", Ok: "#a3be8c", Todo: "#ebcb8b", Event: "#81a1c1", Remind: "#d08770", Danger: "#bf616a"},
|
|
{Name: "dracula", Dark: true, Accent: "#bd93f9", Dim: "#6272a4", Muted: "#bfbfbf", Ok: "#50fa7b", Todo: "#f1fa8c", Event: "#8be9fd", Remind: "#ffb86c", Danger: "#ff5555"},
|
|
{Name: "gruvbox", Dark: true, Accent: "#fabd2f", Dim: "#665c54", Muted: "#a89984", Ok: "#b8bb26", Todo: "#fabd2f", Event: "#83a598", Remind: "#fe8019", Danger: "#fb4934"},
|
|
{Name: "rosepine", Dark: true, Accent: "#c4a7e7", Dim: "#6e6a86", Muted: "#908caa", Ok: "#a6da95", Todo: "#f6c177", Event: "#31748f", Remind: "#ea9a97", Danger: "#eb6f92"},
|
|
{Name: "tokyonight", Dark: true, Accent: "#7aa2f7", Dim: "#565f89", Muted: "#a9b1d6", Ok: "#9ece6a", Todo: "#e0af68", Event: "#7aa2f7", Remind: "#ff9e64", Danger: "#f7768e"},
|
|
{Name: "solarized", Dark: true, Accent: "#268bd2", Dim: "#586e75", Muted: "#657b83", Ok: "#859900", Todo: "#b58900", Event: "#268bd2", Remind: "#cb4b16", Danger: "#dc322f"},
|
|
{Name: "paper", Dark: false, Accent: "#8a6018", Dim: "#a09080", Muted: "#6a5e50", Ok: "#2a6828", Todo: "#7a5c00", Event: "#245890", Remind: "#984020", Danger: "#882030"},
|
|
{Name: "catppuccin-latte", Dark: false, Accent: "#8839ef", Dim: "#9ca0b0", Muted: "#6c6f85", Ok: "#40a02b", Todo: "#df8e1d", Event: "#1e66f5", Remind: "#fe640b", Danger: "#d20f39"},
|
|
{Name: "rosepine-dawn", Dark: false, Accent: "#907aa9", Dim: "#9893a5", Muted: "#797593", Ok: "#56949f", Todo: "#ea9d34", Event: "#286983", Remind: "#d7827e", Danger: "#b4637a"},
|
|
{Name: "solarized-light", Dark: false, Accent: "#268bd2", Dim: "#93a1a1", Muted: "#586e75", Ok: "#859900", Todo: "#b58900", Event: "#268bd2", Remind: "#cb4b16", Danger: "#dc322f"},
|
|
}
|
|
|
|
var activeThemeIndex int
|
|
|
|
func activeTheme() Theme {
|
|
return themes[activeThemeIndex]
|
|
}
|
|
|
|
func cycleTheme() Theme {
|
|
activeThemeIndex = (activeThemeIndex + 1) % len(themes)
|
|
applyTheme()
|
|
saveTheme()
|
|
return themes[activeThemeIndex]
|
|
}
|
|
|
|
func glamourStyle() string {
|
|
if themes[activeThemeIndex].Dark {
|
|
return "dark"
|
|
}
|
|
return "light"
|
|
}
|
|
|
|
func themePath() string {
|
|
home, err := os.UserHomeDir()
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return filepath.Join(home, ".nib", "theme")
|
|
}
|
|
|
|
func loadTheme() {
|
|
p := themePath()
|
|
if p == "" {
|
|
return
|
|
}
|
|
data, err := os.ReadFile(p)
|
|
if err != nil {
|
|
return
|
|
}
|
|
name := strings.TrimSpace(string(data))
|
|
for i, t := range themes {
|
|
if t.Name == name {
|
|
activeThemeIndex = i
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func saveTheme() {
|
|
p := themePath()
|
|
if p == "" {
|
|
return
|
|
}
|
|
_ = os.WriteFile(p, []byte(themes[activeThemeIndex].Name+"\n"), 0o644)
|
|
}
|