feat(tui): add 13 preloaded themes matching web design system
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.
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user