Files
wg-admin/internal/tui/theme/theme.go

247 lines
6.4 KiB
Go

package theme
import (
"fmt"
"os"
"sync"
"github.com/charmbracelet/lipgloss"
)
// ColorScheme defines the color palette for the theme
type ColorScheme struct {
Primary lipgloss.Color
Success lipgloss.Color
Warning lipgloss.Color
Error lipgloss.Color
Muted lipgloss.Color
Background lipgloss.Color
}
// Theme represents a color theme with its name and color scheme
type Theme struct {
Name string
Scheme ColorScheme
}
// Global variables for current theme and styles
var (
currentTheme *Theme
once sync.Once
// Global styles that can be used throughout the application
StylePrimary lipgloss.Style
StyleSuccess lipgloss.Style
StyleWarning lipgloss.Style
StyleError lipgloss.Style
StyleMuted lipgloss.Style
StyleTitle lipgloss.Style
StyleSubtitle lipgloss.Style
StyleHelpKey lipgloss.Style
StyleValue lipgloss.Style
StyleDimmed lipgloss.Style
StyleTableHeader lipgloss.Style
StyleTableSelected lipgloss.Style
StyleBorder lipgloss.Color
StyleBackground lipgloss.Color
)
// DefaultTheme is the standard blue-based theme
var DefaultTheme = &Theme{
Name: "default",
Scheme: ColorScheme{
Primary: lipgloss.Color("62"), // Blue
Success: lipgloss.Color("46"), // Green
Warning: lipgloss.Color("208"), // Orange
Error: lipgloss.Color("196"), // Red
Muted: lipgloss.Color("241"), // Gray
Background: lipgloss.Color(""), // Default terminal background
},
}
// DarkTheme is a purple-based dark theme
var DarkTheme = &Theme{
Name: "dark",
Scheme: ColorScheme{
Primary: lipgloss.Color("141"), // Purple
Success: lipgloss.Color("51"), // Cyan
Warning: lipgloss.Color("226"), // Yellow
Error: lipgloss.Color("196"), // Red
Muted: lipgloss.Color("245"), // Light gray
Background: lipgloss.Color(""), // Default terminal background
},
}
// LightTheme is a green-based light theme
var LightTheme = &Theme{
Name: "light",
Scheme: ColorScheme{
Primary: lipgloss.Color("34"), // Green
Success: lipgloss.Color("36"), // Teal
Warning: lipgloss.Color("214"), // Amber
Error: lipgloss.Color("196"), // Red
Muted: lipgloss.Color("244"), // Gray
Background: lipgloss.Color(""), // Default terminal background
},
}
// DraculaTheme is the popular Dracula dark color scheme
var DraculaTheme = &Theme{
Name: "dracula",
Scheme: ColorScheme{
Primary: lipgloss.Color("#BD93F9"), // Purple
Success: lipgloss.Color("#50FA7B"), // Green
Warning: lipgloss.Color("#FFB86C"), // Orange
Error: lipgloss.Color("#FF5555"), // Red
Muted: lipgloss.Color("#6272A4"), // Light purple-gray
Background: lipgloss.Color("#282A36"), // Dark background
},
}
// EverforestTheme is the natural Everforest dark color scheme
var EverforestTheme = &Theme{
Name: "everforest",
Scheme: ColorScheme{
Primary: lipgloss.Color("#7fbbb3"), // Blue
Success: lipgloss.Color("#a7c080"), // Green
Warning: lipgloss.Color("#dbbc7f"), // Yellow
Error: lipgloss.Color("#e67e80"), // Red
Muted: lipgloss.Color("#414b50"), // Gray
Background: lipgloss.Color("#272e33"), // Dark background
},
}
// ThemeRegistry holds all available themes
var ThemeRegistry = map[string]*Theme{
"default": DefaultTheme,
"dark": DarkTheme,
"light": LightTheme,
"dracula": DraculaTheme,
"everforest": EverforestTheme,
}
// GetTheme loads the theme from config or environment variable
// Returns the default theme if no theme is specified
func GetTheme() (*Theme, error) {
once.Do(func() {
// Try to get theme from environment variable first
themeName := os.Getenv("THEME")
if themeName == "" {
themeName = "everforest"
}
// Look up the theme in the registry
if theme, ok := ThemeRegistry[themeName]; ok {
currentTheme = theme
} else {
// If theme not found, use everforest as default
currentTheme = EverforestTheme
}
// Apply the theme to initialize styles
ApplyTheme(currentTheme)
})
return currentTheme, nil
}
// ApplyTheme applies the given theme to all global styles
func ApplyTheme(theme *Theme) {
currentTheme = theme
// Primary style
StylePrimary = lipgloss.NewStyle().
Foreground(theme.Scheme.Primary)
// Success style
StyleSuccess = lipgloss.NewStyle().
Foreground(theme.Scheme.Success)
// Warning style
StyleWarning = lipgloss.NewStyle().
Foreground(theme.Scheme.Warning)
// Error style
StyleError = lipgloss.NewStyle().
Foreground(theme.Scheme.Error)
// Muted style
StyleMuted = lipgloss.NewStyle().
Foreground(theme.Scheme.Muted)
// Title style (bold primary)
StyleTitle = lipgloss.NewStyle().
Foreground(theme.Scheme.Primary).
Bold(true)
// Subtitle style (muted)
StyleSubtitle = lipgloss.NewStyle().
Foreground(theme.Scheme.Muted)
// Help key style (bold primary, slightly different shade)
StyleHelpKey = lipgloss.NewStyle().
Foreground(theme.Scheme.Primary).
Bold(true)
// Value style for content values
StyleValue = lipgloss.NewStyle().
Foreground(lipgloss.Color("255"))
// Dimmed style for overlay content
StyleDimmed = lipgloss.NewStyle().
Foreground(theme.Scheme.Muted)
// Table header style
StyleTableHeader = lipgloss.NewStyle().
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color("240")).
BorderBottom(true).
Bold(true)
// Table selected style
StyleTableSelected = lipgloss.NewStyle().
Foreground(lipgloss.Color("229")).
Background(lipgloss.Color("57")).
Bold(false)
// Border color
StyleBorder = lipgloss.Color("240")
// Background color for modals
StyleBackground = lipgloss.Color("235")
}
// GetThemeNames returns a list of available theme names
func GetThemeNames() []string {
names := make([]string, 0, len(ThemeRegistry))
for name := range ThemeRegistry {
names = append(names, name)
}
return names
}
// SetTheme changes the current theme by name
func SetTheme(name string) error {
theme, ok := ThemeRegistry[name]
if !ok {
return fmt.Errorf("theme '%s' not found. Available themes: %v", name, GetThemeNames())
}
ApplyTheme(theme)
return nil
}
// GetCurrentTheme returns the currently active theme
func GetCurrentTheme() *Theme {
if currentTheme == nil {
currentTheme = DefaultTheme
ApplyTheme(currentTheme)
}
return currentTheme
}
// GetColorScheme returns the color scheme of the current theme
func GetColorScheme() ColorScheme {
return GetCurrentTheme().Scheme
}