87edd4aa40
Light theme doesn't work well on dark terminals. Replace with two proven dark palettes. Now 5 themes: Flexoki Dark, Tokyo Night, Catppuccin Mocha, Nord, Gruvbox.
192 lines
5.0 KiB
Go
192 lines
5.0 KiB
Go
package tui
|
|
|
|
import (
|
|
"github.com/charmbracelet/huh"
|
|
"github.com/charmbracelet/lipgloss"
|
|
)
|
|
|
|
type Theme struct {
|
|
Name string
|
|
|
|
// Base layers
|
|
Bg lipgloss.Color
|
|
Surface lipgloss.Color
|
|
Panel lipgloss.Color
|
|
Border lipgloss.Color
|
|
|
|
// Text
|
|
Fg lipgloss.Color
|
|
Muted lipgloss.Color
|
|
Subtle lipgloss.Color
|
|
|
|
// Semantic
|
|
Success lipgloss.Color
|
|
Warning lipgloss.Color
|
|
Danger lipgloss.Color
|
|
Info lipgloss.Color
|
|
Accent lipgloss.Color
|
|
Purple lipgloss.Color
|
|
|
|
// Table
|
|
ZebraBg lipgloss.Color
|
|
|
|
// Selection
|
|
SelectedFg lipgloss.Color
|
|
SelectedBg lipgloss.Color
|
|
}
|
|
|
|
var themes = []Theme{
|
|
themeFlexokiDark,
|
|
themeTokyoNight,
|
|
themeCatppuccinMocha,
|
|
themeNord,
|
|
themeGruvbox,
|
|
}
|
|
|
|
var themeFlexokiDark = Theme{
|
|
Name: "Flexoki Dark",
|
|
Bg: "#1C1B1A",
|
|
Surface: "#282726",
|
|
Panel: "#343331",
|
|
Border: "#575653",
|
|
Fg: "#CECDC3",
|
|
Muted: "#878580",
|
|
Subtle: "#6F6E69",
|
|
Success: "#879A39",
|
|
Warning: "#D0A215",
|
|
Danger: "#D14D41",
|
|
Info: "#4385BE",
|
|
Accent: "#3AA99F",
|
|
Purple: "#8B7EC8",
|
|
ZebraBg: "#222120",
|
|
SelectedFg: "#FFFCF0",
|
|
SelectedBg: "#403E3C",
|
|
}
|
|
|
|
var themeTokyoNight = Theme{
|
|
Name: "Tokyo Night",
|
|
Bg: "#1a1b26",
|
|
Surface: "#24283b",
|
|
Panel: "#292e42",
|
|
Border: "#3b4261",
|
|
Fg: "#c0caf5",
|
|
Muted: "#a9b1d6",
|
|
Subtle: "#565f89",
|
|
Success: "#9ece6a",
|
|
Warning: "#e0af68",
|
|
Danger: "#f7768e",
|
|
Info: "#7aa2f7",
|
|
Accent: "#7dcfff",
|
|
Purple: "#bb9af7",
|
|
ZebraBg: "#1e1f2b",
|
|
SelectedFg: "#c0caf5",
|
|
SelectedBg: "#292e42",
|
|
}
|
|
|
|
var themeGruvbox = Theme{
|
|
Name: "Gruvbox",
|
|
Bg: "#282828",
|
|
Surface: "#3c3836",
|
|
Panel: "#504945",
|
|
Border: "#665c54",
|
|
Fg: "#ebdbb2",
|
|
Muted: "#bdae93",
|
|
Subtle: "#7c6f64",
|
|
Success: "#b8bb26",
|
|
Warning: "#fabd2f",
|
|
Danger: "#fb4934",
|
|
Info: "#83a598",
|
|
Accent: "#8ec07c",
|
|
Purple: "#d3869b",
|
|
ZebraBg: "#2e2c2a",
|
|
SelectedFg: "#fbf1c7",
|
|
SelectedBg: "#504945",
|
|
}
|
|
|
|
var themeCatppuccinMocha = Theme{
|
|
Name: "Catppuccin Mocha",
|
|
Bg: "#1e1e2e",
|
|
Surface: "#313244",
|
|
Panel: "#45475a",
|
|
Border: "#585b70",
|
|
Fg: "#cdd6f4",
|
|
Muted: "#a6adc8",
|
|
Subtle: "#6c7086",
|
|
Success: "#a6e3a1",
|
|
Warning: "#f9e2af",
|
|
Danger: "#f38ba8",
|
|
Info: "#89b4fa",
|
|
Accent: "#94e2d5",
|
|
Purple: "#cba6f7",
|
|
ZebraBg: "#232334",
|
|
SelectedFg: "#cdd6f4",
|
|
SelectedBg: "#45475a",
|
|
}
|
|
|
|
var themeNord = Theme{
|
|
Name: "Nord",
|
|
Bg: "#2e3440",
|
|
Surface: "#3b4252",
|
|
Panel: "#434c5e",
|
|
Border: "#4c566a",
|
|
Fg: "#d8dee9",
|
|
Muted: "#d8dee9",
|
|
Subtle: "#4c566a",
|
|
Success: "#a3be8c",
|
|
Warning: "#ebcb8b",
|
|
Danger: "#bf616a",
|
|
Info: "#81a1c1",
|
|
Accent: "#88c0d0",
|
|
Purple: "#b48ead",
|
|
ZebraBg: "#323845",
|
|
SelectedFg: "#eceff4",
|
|
SelectedBg: "#434c5e",
|
|
}
|
|
|
|
func (t Theme) HuhTheme() *huh.Theme {
|
|
ht := huh.ThemeBase()
|
|
|
|
ht.Focused.Base = ht.Focused.Base.BorderForeground(t.Border)
|
|
ht.Focused.Card = ht.Focused.Base
|
|
ht.Focused.Title = ht.Focused.Title.Foreground(t.Accent).Bold(true)
|
|
ht.Focused.NoteTitle = ht.Focused.NoteTitle.Foreground(t.Accent).Bold(true).MarginBottom(1)
|
|
ht.Focused.Description = ht.Focused.Description.Foreground(t.Muted)
|
|
ht.Focused.ErrorIndicator = ht.Focused.ErrorIndicator.Foreground(t.Danger)
|
|
ht.Focused.ErrorMessage = ht.Focused.ErrorMessage.Foreground(t.Danger)
|
|
ht.Focused.SelectSelector = ht.Focused.SelectSelector.Foreground(t.Purple)
|
|
ht.Focused.NextIndicator = ht.Focused.NextIndicator.Foreground(t.Purple)
|
|
ht.Focused.PrevIndicator = ht.Focused.PrevIndicator.Foreground(t.Purple)
|
|
ht.Focused.Option = ht.Focused.Option.Foreground(t.Fg)
|
|
ht.Focused.MultiSelectSelector = ht.Focused.MultiSelectSelector.Foreground(t.Purple)
|
|
ht.Focused.SelectedOption = ht.Focused.SelectedOption.Foreground(t.Success)
|
|
ht.Focused.SelectedPrefix = lipgloss.NewStyle().Foreground(t.Success).SetString("✓ ")
|
|
ht.Focused.UnselectedPrefix = lipgloss.NewStyle().Foreground(t.Subtle).SetString("• ")
|
|
ht.Focused.UnselectedOption = ht.Focused.UnselectedOption.Foreground(t.Fg)
|
|
ht.Focused.FocusedButton = ht.Focused.FocusedButton.Foreground(t.Bg).Background(t.Accent)
|
|
ht.Focused.Next = ht.Focused.FocusedButton
|
|
ht.Focused.BlurredButton = ht.Focused.BlurredButton.Foreground(t.Fg).Background(t.Surface)
|
|
ht.Focused.TextInput.Cursor = ht.Focused.TextInput.Cursor.Foreground(t.Accent)
|
|
ht.Focused.TextInput.Placeholder = ht.Focused.TextInput.Placeholder.Foreground(t.Subtle)
|
|
ht.Focused.TextInput.Prompt = ht.Focused.TextInput.Prompt.Foreground(t.Purple)
|
|
|
|
ht.Blurred = ht.Focused
|
|
ht.Blurred.Base = ht.Focused.Base.BorderStyle(lipgloss.HiddenBorder())
|
|
ht.Blurred.Card = ht.Blurred.Base
|
|
ht.Blurred.NextIndicator = lipgloss.NewStyle()
|
|
ht.Blurred.PrevIndicator = lipgloss.NewStyle()
|
|
|
|
ht.Group.Title = ht.Focused.Title
|
|
ht.Group.Description = ht.Focused.Description
|
|
|
|
return ht
|
|
}
|
|
|
|
func themeByName(name string) Theme {
|
|
for _, t := range themes {
|
|
if t.Name == name {
|
|
return t
|
|
}
|
|
}
|
|
return themes[0]
|
|
}
|