styles

package
v0.74.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 19, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package styles defines the visual design system including color palettes, lipgloss styles, gradient tabs, and theme application for consistent UI rendering.

Index

Constants

View Source
const ANSIReset = "\x1b[0m"

ANSIReset is the ANSI escape code to reset formatting.

View Source
const DefaultGradientAngle = 30.0

DefaultGradientAngle is the default angle for gradient borders (30 degrees).

Variables

View Source
var (
	// Primary colors
	Primary   = lipgloss.Color("#7C3AED") // Purple
	Secondary = lipgloss.Color("#3B82F6") // Blue
	Accent    = lipgloss.Color("#F59E0B") // Amber

	// Status colors
	Success = lipgloss.Color("#10B981") // Green
	Warning = lipgloss.Color("#F59E0B") // Amber
	Error   = lipgloss.Color("#EF4444") // Red
	Info    = lipgloss.Color("#3B82F6") // Blue

	// Text colors
	TextPrimary        = lipgloss.Color("#F9FAFB")
	TextSecondary      = lipgloss.Color("#9CA3AF")
	TextMuted          = lipgloss.Color("#6B7280")
	TextSubtle         = lipgloss.Color("#4B5563")
	TextSelectionColor = lipgloss.Color("#F9FAFB") // Text on selection backgrounds (BgTertiary)

	// Background colors
	BgPrimary   = lipgloss.Color("#111827")
	BgSecondary = lipgloss.Color("#1F2937")
	BgTertiary  = lipgloss.Color("#374151")
	BgOverlay   = lipgloss.Color("#00000080")

	// Border colors
	BorderNormal = lipgloss.Color("#374151")
	BorderActive = lipgloss.Color("#7C3AED")
	BorderMuted  = lipgloss.Color("#1F2937")

	// Diff foreground colors (also updated by ApplyTheme)
	DiffAddFg    = lipgloss.Color("#10B981")
	DiffRemoveFg = lipgloss.Color("#EF4444")

	// Additional themeable colors
	TextHighlight         = lipgloss.Color("#E5E7EB") // For subtitle, special text
	ButtonHoverColor      = lipgloss.Color("#9D174D") // Button hover background
	TabTextInactiveColor  = lipgloss.Color("#1a1a1a") // Inactive tab text
	LinkColor             = lipgloss.Color("#60A5FA") // Hyperlink color
	ToastSuccessTextColor = lipgloss.Color("#000000") // Toast success foreground
	ToastErrorTextColor   = lipgloss.Color("#FFFFFF") // Toast error foreground

	// Danger button colors
	DangerLight  = lipgloss.Color("#FCA5A5") // Light red text
	DangerDark   = lipgloss.Color("#7F1D1D") // Dark red background
	DangerBright = lipgloss.Color("#DC2626") // Bright red focused bg
	DangerHover  = lipgloss.Color("#B91C1C") // Darker red hover bg
	TextInverse  = lipgloss.Color("#FFFFFF") // Inverse/contrast text

	// Scrollbar colors (default to TextSubtle/TextMuted)
	ScrollbarTrackColor = lipgloss.Color("#4B5563") // Same as TextSubtle
	ScrollbarThumbColor = lipgloss.Color("#6B7280") // Same as TextMuted

	// Blame age gradient colors
	BlameAge1 = lipgloss.Color("#34D399") // < 1 week
	BlameAge2 = lipgloss.Color("#84CC16") // < 1 month
	BlameAge3 = lipgloss.Color("#FBBF24") // < 3 months
	BlameAge4 = lipgloss.Color("#F97316") // < 6 months
	BlameAge5 = lipgloss.Color("#9CA3AF") // < 1 year

	// Third-party theme names (updated by ApplyTheme)
	CurrentSyntaxTheme   = "monokai"
	CurrentMarkdownTheme = "dark"
)

Color palette - default dark theme

View Source
var (
	CurrentTabStyle  = "rainbow"
	CurrentTabColors = []RGB{{220, 60, 60}, {60, 220, 60}, {60, 60, 220}, {156, 60, 220}} // Default rainbow
)

Tab theme state (updated by ApplyTheme)

View Source
var (
	// Active panel with highlighted border
	PanelActive = lipgloss.NewStyle().
				Border(lipgloss.RoundedBorder()).
				BorderForeground(BorderActive).
				Padding(0, 1)

	// Inactive panel with subtle border
	PanelInactive = lipgloss.NewStyle().
					Border(lipgloss.RoundedBorder()).
					BorderForeground(BorderNormal).
					Padding(0, 1)

	// Panel header
	PanelHeader = lipgloss.NewStyle().
				Bold(true).
				Foreground(TextPrimary).
				MarginBottom(1)

	// Panel with no border
	PanelNoBorder = lipgloss.NewStyle().
					Padding(0, 1)
)

Panel styles

View Source
var (
	Title = lipgloss.NewStyle().
			Bold(true).
			Foreground(TextPrimary)

	Subtitle = lipgloss.NewStyle().
				Foreground(TextHighlight)

	// WorktreeIndicator shows the current worktree branch in the header
	WorktreeIndicator = lipgloss.NewStyle().
						Foreground(Warning).
						Bold(true)

	Body = lipgloss.NewStyle().
			Foreground(TextPrimary)

	Muted = lipgloss.NewStyle().
			Foreground(TextMuted)

	Subtle = lipgloss.NewStyle().
			Foreground(TextSubtle)

	Code = lipgloss.NewStyle().
			Foreground(Accent)

	Link = lipgloss.NewStyle().
			Foreground(LinkColor).
			Underline(true)

	KeyHint = lipgloss.NewStyle().
			Foreground(TextMuted).
			Background(BgTertiary).
			Padding(0, 1)

			Foreground(Primary).
			Bold(true)
)

Text styles

View Source
var (
	StatusStaged = lipgloss.NewStyle().
					Foreground(Success).
					Bold(true)

	StatusModified = lipgloss.NewStyle().
					Foreground(Warning).
					Bold(true)

	// Toast styles for status messages
	ToastSuccess = lipgloss.NewStyle().
					Background(Success).
					Foreground(ToastSuccessTextColor).
					Bold(true).
					Padding(0, 1)

	ToastError = lipgloss.NewStyle().
				Background(Error).
				Foreground(ToastErrorTextColor).
				Bold(true).
				Padding(0, 1)

	StatusUntracked = lipgloss.NewStyle().
					Foreground(TextMuted)

	StatusDeleted = lipgloss.NewStyle().
					Foreground(Error).
					Bold(true)

	StatusInProgress = lipgloss.NewStyle().
						Foreground(Info).
						Bold(true)

	StatusCompleted = lipgloss.NewStyle().
					Foreground(Success)

	StatusBlocked = lipgloss.NewStyle().
					Foreground(Error)

	StatusPending = lipgloss.NewStyle().
					Foreground(TextMuted)

	// Note status indicator styles
	StatusArchived = lipgloss.NewStyle().
					Foreground(Info)

	StatusDeletedNote = lipgloss.NewStyle().
						Foreground(Error)
)

Status indicator styles

View Source
var (
	ListItemNormal = lipgloss.NewStyle().
					Foreground(TextPrimary)

	ListItemSelected = lipgloss.NewStyle().
						Foreground(TextSelectionColor).
						Background(BgTertiary)

	ListItemFocused = lipgloss.NewStyle().
					Foreground(TextPrimary).
					Background(Primary)

	ListCursor = lipgloss.NewStyle().
				Foreground(Primary).
				Bold(true)
)

List item styles

View Source
var (
	BarTitle = lipgloss.NewStyle().
				Foreground(TextPrimary).
				Bold(true)

	BarText = lipgloss.NewStyle().
			Foreground(TextMuted)

	BarChip = lipgloss.NewStyle().
			Foreground(TextMuted).
			Background(BgTertiary).
			Padding(0, 1)

	BarChipActive = lipgloss.NewStyle().
					Foreground(TextPrimary).
					Background(Primary).
					Padding(0, 1).
					Bold(true)
)

Bar element styles (shared by header/footer)

View Source
var (
	DiffAdd = lipgloss.NewStyle().
			Foreground(Success)

	DiffRemove = lipgloss.NewStyle().
				Foreground(Error)

	DiffContext = lipgloss.NewStyle().
				Foreground(TextMuted)

	DiffHeader = lipgloss.NewStyle().
				Foreground(Info).
				Bold(true)

	// Subtle diff backgrounds for syntax-highlighted lines
	DiffAddBg    = lipgloss.Color("#0D2818") // Very subtle dark green
	DiffRemoveBg = lipgloss.Color("#2D1A1A") // Very subtle dark red
)

Diff line styles

View Source
var (
	// Directory names - bold blue
	FileBrowserDir = lipgloss.NewStyle().
					Foreground(Secondary).
					Bold(true)

	// Regular file names
	FileBrowserFile = lipgloss.NewStyle().
					Foreground(TextPrimary)

	// Gitignored files - muted/dimmed
	FileBrowserIgnored = lipgloss.NewStyle().
						Foreground(TextSubtle)

	// Line numbers in preview
	FileBrowserLineNumber = lipgloss.NewStyle().
							Foreground(TextMuted).
							Width(5).
							AlignHorizontal(lipgloss.Right)

	// Tree icons (>, +)
	FileBrowserIcon = lipgloss.NewStyle().
					Foreground(TextMuted)

	// Content search match highlighting
	SearchMatch = lipgloss.NewStyle().
				Background(Warning) // Yellow background for all matches

	SearchMatchCurrent = lipgloss.NewStyle().
						Background(Primary).
						Foreground(TextPrimary)

	// Fuzzy match character highlighting (bold in result list)
	FuzzyMatchChar = lipgloss.NewStyle().
					Foreground(Primary).
					Bold(true)

	// Quick open result row (normal)
	QuickOpenItem = lipgloss.NewStyle().
					Foreground(TextPrimary)

	// Quick open result row (selected)
	QuickOpenItemSelected = lipgloss.NewStyle().
							Foreground(TextSelectionColor).
							Background(BgTertiary)

	// Palette entry styles (reusable for modals)
	PaletteEntry = lipgloss.NewStyle().
					Foreground(TextPrimary)

	PaletteEntrySelected = lipgloss.NewStyle().
							Foreground(TextSelectionColor).
							Background(BgTertiary)

	PaletteKey = lipgloss.NewStyle().
				Foreground(TextMuted).
				Background(BgTertiary).
				Padding(0, 1)

	// Text selection for preview pane drag selection
	TextSelection = lipgloss.NewStyle().
					Background(BgTertiary).
					Foreground(TextSelectionColor)
)

File browser styles

View Source
var (
	Footer = lipgloss.NewStyle().
			Foreground(TextMuted).
			Background(BgSecondary)

	Header = lipgloss.NewStyle().
			Background(BgSecondary)
)

Footer and header

View Source
var (
	ModalOverlay = lipgloss.NewStyle().
					Background(BgOverlay)

	ModalBox = lipgloss.NewStyle().
				Border(lipgloss.RoundedBorder()).
				BorderForeground(Primary).
				Background(BgSecondary).
				Padding(1, 2)

	ModalTitle = lipgloss.NewStyle().
				Foreground(TextPrimary).
				Bold(true).
				MarginBottom(1)
)

Modal styles

View Source
var (
	Button = lipgloss.NewStyle().
			Foreground(TextSecondary).
			Background(BgTertiary).
			Padding(0, 2)

	ButtonFocused = lipgloss.NewStyle().
					Foreground(TextPrimary).
					Background(Primary).
					Padding(0, 2).
					Bold(true)

	ButtonHover = lipgloss.NewStyle().
				Foreground(TextPrimary).
				Background(ButtonHoverColor).
				Padding(0, 2)

	// Danger button styles (for destructive actions like delete)
	ButtonDanger = lipgloss.NewStyle().
					Foreground(DangerLight).
					Background(DangerDark).
					Padding(0, 2)

	ButtonDangerFocused = lipgloss.NewStyle().
						Foreground(TextInverse).
						Background(DangerBright).
						Padding(0, 2).
						Bold(true)

	ButtonDangerHover = lipgloss.NewStyle().
						Foreground(TextInverse).
						Background(DangerHover).
						Padding(0, 2)
)

Button styles

View Source
var (
	// DefaultTheme is the current dark theme (backwards compatible)
	DefaultTheme = Theme{
		Name:        "default",
		DisplayName: "Default Dark",
		Colors: ColorPalette{

			Primary:   "#7C3AED",
			Secondary: "#3B82F6",
			Accent:    "#F59E0B",

			Success: "#10B981",
			Warning: "#F59E0B",
			Error:   "#EF4444",
			Info:    "#3B82F6",

			TextPrimary:   "#F9FAFB",
			TextSecondary: "#9CA3AF",
			TextMuted:     "#6B7280",
			TextSubtle:    "#4B5563",
			TextSelection: "#F9FAFB",

			BgPrimary:   "#111827",
			BgSecondary: "#1F2937",
			BgTertiary:  "#374151",
			BgOverlay:   "#00000080",

			BorderNormal: "#374151",
			BorderActive: "#7C3AED",
			BorderMuted:  "#1F2937",

			GradientBorderActive: []string{"#7C3AED", "#3B82F6"},
			GradientBorderNormal: []string{"#374151", "#2D3748"},
			GradientBorderAngle:  30.0,

			TabStyle:  "rainbow",
			TabColors: []string{"#DC3C3C", "#3CDC3C", "#3C3CDC", "#9C3CDC"},

			DiffAddFg:    "#10B981",
			DiffAddBg:    "#0D2818",
			DiffRemoveFg: "#EF4444",
			DiffRemoveBg: "#2D1A1A",

			TextHighlight:    "#E5E7EB",
			ButtonHover:      "#9D174D",
			TabTextInactive:  "#1a1a1a",
			Link:             "#60A5FA",
			ToastSuccessText: "#000000",
			ToastErrorText:   "#FFFFFF",

			DangerLight:  "#FCA5A5",
			DangerDark:   "#7F1D1D",
			DangerBright: "#DC2626",
			DangerHover:  "#B91C1C",
			TextInverse:  "#FFFFFF",

			BlameAge1: "#34D399",
			BlameAge2: "#84CC16",
			BlameAge3: "#FBBF24",
			BlameAge4: "#F97316",
			BlameAge5: "#9CA3AF",

			SyntaxTheme:   "monokai",
			MarkdownTheme: "dark",
		},
	}

	// DraculaTheme is a Dracula-inspired dark theme with vibrant colors
	DraculaTheme = Theme{
		Name:        "dracula",
		DisplayName: "Dracula",
		Colors: ColorPalette{

			Primary:   "#BD93F9",
			Secondary: "#8BE9FD",
			Accent:    "#FFB86C",

			Success: "#50FA7B",
			Warning: "#FFB86C",
			Error:   "#FF5555",
			Info:    "#8BE9FD",

			TextPrimary:   "#F8F8F2",
			TextSecondary: "#BFBFBF",
			TextMuted:     "#6272A4",
			TextSubtle:    "#44475A",
			TextSelection: "#F8F8F2",

			BgPrimary:   "#282A36",
			BgSecondary: "#343746",
			BgTertiary:  "#44475A",
			BgOverlay:   "#00000080",

			BorderNormal: "#44475A",
			BorderActive: "#BD93F9",
			BorderMuted:  "#343746",

			GradientBorderActive: []string{"#BD93F9", "#8BE9FD"},
			GradientBorderNormal: []string{"#44475A", "#383A4A"},
			GradientBorderAngle:  30.0,

			TabStyle:  "gradient",
			TabColors: []string{"#BD93F9", "#FF79C6", "#8BE9FD"},

			DiffAddFg:    "#50FA7B",
			DiffAddBg:    "#1E3A29",
			DiffRemoveFg: "#FF5555",
			DiffRemoveBg: "#3D2A2A",

			TextHighlight:    "#F8F8F2",
			ButtonHover:      "#FF79C6",
			TabTextInactive:  "#282A36",
			Link:             "#8BE9FD",
			ToastSuccessText: "#282A36",
			ToastErrorText:   "#F8F8F2",

			DangerLight:  "#FFADAD",
			DangerDark:   "#3D1F1F",
			DangerBright: "#FF5555",
			DangerHover:  "#E63E3E",
			TextInverse:  "#F8F8F2",

			BlameAge1: "#69FF94",
			BlameAge2: "#A4E22E",
			BlameAge3: "#FFB86C",
			BlameAge4: "#FF7979",
			BlameAge5: "#6272A4",

			SyntaxTheme:   "dracula",
			MarkdownTheme: "dark",
		},
	}

	// MolokaiTheme is a vibrant, high-contrast theme
	MolokaiTheme = Theme{
		Name:        "molokai",
		DisplayName: "Molokai",
		Colors: ColorPalette{
			Primary:   "#F92672",
			Secondary: "#66D9EF",
			Accent:    "#A6E22E",

			Success: "#A6E22E",
			Warning: "#FD971F",
			Error:   "#F92672",
			Info:    "#66D9EF",

			TextPrimary:   "#F8F8F2",
			TextSecondary: "#CFD0C2",
			TextMuted:     "#75715E",
			TextSubtle:    "#465457",
			TextSelection: "#F8F8F2",

			BgPrimary:   "#1B1D1E",
			BgSecondary: "#272822",
			BgTertiary:  "#3E3D32",
			BgOverlay:   "#00000080",

			BorderNormal: "#465457",
			BorderActive: "#F92672",
			BorderMuted:  "#3E3D32",

			GradientBorderActive: []string{"#F92672", "#A6E22E"},
			GradientBorderNormal: []string{"#465457", "#3E3D32"},
			GradientBorderAngle:  45.0,

			TabStyle:  "solid",
			TabColors: []string{"#F92672"},

			DiffAddFg:    "#A6E22E",
			DiffAddBg:    "#13210C",
			DiffRemoveFg: "#F92672",
			DiffRemoveBg: "#210C11",

			TextHighlight:    "#E6DB74",
			ButtonHover:      "#F92672",
			TabTextInactive:  "#75715E",
			Link:             "#66D9EF",
			ToastSuccessText: "#1B1D1E",
			ToastErrorText:   "#F8F8F2",

			DangerLight:  "#F8A0B8",
			DangerDark:   "#3D0F1E",
			DangerBright: "#F92672",
			DangerHover:  "#D91E63",
			TextInverse:  "#F8F8F2",

			BlameAge1: "#A6E22E",
			BlameAge2: "#E6DB74",
			BlameAge3: "#FD971F",
			BlameAge4: "#F92672",
			BlameAge5: "#75715E",

			SyntaxTheme:   "monokai",
			MarkdownTheme: "dark",
		},
	}

	// NordTheme is an arctic, north-bluish color palette
	NordTheme = Theme{
		Name:        "nord",
		DisplayName: "Nord",
		Colors: ColorPalette{
			Primary:   "#88C0D0",
			Secondary: "#81A1C1",
			Accent:    "#EBCB8B",

			Success: "#A3BE8C",
			Warning: "#EBCB8B",
			Error:   "#BF616A",
			Info:    "#88C0D0",

			TextPrimary:   "#D8DEE9",
			TextSecondary: "#E5E9F0",
			TextMuted:     "#4C566A",
			TextSubtle:    "#434C5E",
			TextSelection: "#D8DEE9",

			BgPrimary:   "#2E3440",
			BgSecondary: "#3B4252",
			BgTertiary:  "#434C5E",
			BgOverlay:   "#2E3440CC",

			BorderNormal: "#4C566A",
			BorderActive: "#88C0D0",
			BorderMuted:  "#3B4252",

			GradientBorderActive: []string{"#88C0D0", "#81A1C1"},
			GradientBorderNormal: []string{"#434C5E", "#3B4252"},
			GradientBorderAngle:  120.0,

			TabStyle:  "minimal",
			TabColors: []string{"#88C0D0"},

			DiffAddFg:    "#A3BE8C",
			DiffAddBg:    "#233129",
			DiffRemoveFg: "#BF616A",
			DiffRemoveBg: "#312325",

			TextHighlight:    "#ECEFF4",
			ButtonHover:      "#5E81AC",
			TabTextInactive:  "#4C566A",
			Link:             "#88C0D0",
			ToastSuccessText: "#2E3440",
			ToastErrorText:   "#E5E9F0",

			DangerLight:  "#D08770",
			DangerDark:   "#3B2A25",
			DangerBright: "#BF616A",
			DangerHover:  "#A5545C",
			TextInverse:  "#ECEFF4",

			BlameAge1: "#A3BE8C",
			BlameAge2: "#EBCB8B",
			BlameAge3: "#D08770",
			BlameAge4: "#BF616A",
			BlameAge5: "#4C566A",

			SyntaxTheme:   "nord",
			MarkdownTheme: "dark",
		},
	}

	// SolarizedDarkTheme is a precision color scheme
	SolarizedDarkTheme = Theme{
		Name:        "solarized-dark",
		DisplayName: "Solarized Dark",
		Colors: ColorPalette{
			Primary:   "#268BD2",
			Secondary: "#2AA198",
			Accent:    "#B58900",

			Success: "#859900",
			Warning: "#B58900",
			Error:   "#DC322F",
			Info:    "#268BD2",

			TextPrimary:   "#93A1A1",
			TextSecondary: "#839496",
			TextMuted:     "#586E75",
			TextSubtle:    "#073642",
			TextSelection: "#93A1A1",

			BgPrimary:   "#002B36",
			BgSecondary: "#073642",
			BgTertiary:  "#002B36",
			BgOverlay:   "#00181ECC",

			BorderNormal: "#586E75",
			BorderActive: "#268BD2",
			BorderMuted:  "#073642",

			GradientBorderActive: []string{"#268BD2", "#2AA198"},
			GradientBorderNormal: []string{"#586E75", "#073642"},
			GradientBorderAngle:  90.0,

			TabStyle:  "solid",
			TabColors: []string{"#2AA198"},

			DiffAddFg:    "#859900",
			DiffAddBg:    "#002B36",
			DiffRemoveFg: "#DC322F",
			DiffRemoveBg: "#002B36",

			TextHighlight:    "#FDF6E3",
			ButtonHover:      "#CB4B16",
			TabTextInactive:  "#586E75",
			Link:             "#268BD2",
			ToastSuccessText: "#FDF6E3",
			ToastErrorText:   "#FDF6E3",

			DangerLight:  "#E8A0A0",
			DangerDark:   "#2A1515",
			DangerBright: "#DC322F",
			DangerHover:  "#C12926",
			TextInverse:  "#FDF6E3",

			BlameAge1: "#859900",
			BlameAge2: "#B58900",
			BlameAge3: "#CB4B16",
			BlameAge4: "#DC322F",
			BlameAge5: "#586E75",

			SyntaxTheme:   "solarized-dark",
			MarkdownTheme: "dark",
		},
	}

	// TokyoNightTheme is a clean, dark theme that celebrates the lights of Downtown Tokyo
	TokyoNightTheme = Theme{
		Name:        "tokyo-night",
		DisplayName: "Tokyo Night",
		Colors: ColorPalette{
			Primary:   "#7AA2F7",
			Secondary: "#BB9AF7",
			Accent:    "#FF9E64",

			Success: "#9ECE6A",
			Warning: "#E0AF68",
			Error:   "#F7768E",
			Info:    "#7DCFFF",

			TextPrimary:   "#C0CAF5",
			TextSecondary: "#A9B1D6",
			TextMuted:     "#565F89",
			TextSubtle:    "#414868",
			TextSelection: "#C0CAF5",

			BgPrimary:   "#1A1B26",
			BgSecondary: "#24283B",
			BgTertiary:  "#414868",
			BgOverlay:   "#15161ECC",

			BorderNormal: "#565F89",
			BorderActive: "#7AA2F7",
			BorderMuted:  "#24283B",

			GradientBorderActive: []string{"#7AA2F7", "#BB9AF7"},
			GradientBorderNormal: []string{"#565F89", "#414868"},
			GradientBorderAngle:  60.0,

			TabStyle:  "gradient",
			TabColors: []string{"#7AA2F7", "#BB9AF7", "#F7768E"},

			DiffAddFg:    "#9ECE6A",
			DiffAddBg:    "#283B4D",
			DiffRemoveFg: "#F7768E",
			DiffRemoveBg: "#3F2D3D",

			TextHighlight:    "#C0CAF5",
			ButtonHover:      "#BB9AF7",
			TabTextInactive:  "#565F89",
			Link:             "#73DACA",
			ToastSuccessText: "#15161E",
			ToastErrorText:   "#C0CAF5",

			DangerLight:  "#F7A8B8",
			DangerDark:   "#2D1520",
			DangerBright: "#F7768E",
			DangerHover:  "#E05F77",
			TextInverse:  "#C0CAF5",

			BlameAge1: "#9ECE6A",
			BlameAge2: "#E0AF68",
			BlameAge3: "#FF9E64",
			BlameAge4: "#F7768E",
			BlameAge5: "#565F89",

			SyntaxTheme:   "tokyo-night",
			MarkdownTheme: "dark",
		},
	}
)

Built-in themes

View Source
var PillTabsEnabled = false

PillTabsEnabled enables rounded pill-style tabs (requires Nerd Font)

View Source
var TabTextActive = lipgloss.NewStyle().
	Foreground(TextPrimary).
	Bold(true)

TabTextActive is the text color for active tabs

View Source
var TabTextInactive = lipgloss.NewStyle().
	Foreground(TabTextInactiveColor)

TabTextInactive is the text color for inactive tabs

View Source
var TabThemePresets = map[string]TabThemePreset{

	"rainbow": {
		Name:        "rainbow",
		DisplayName: "Rainbow",
		Style:       "gradient",
		Colors:      []string{"#DC3C3C", "#3CDC3C", "#3C3CDC", "#9C3CDC"},
	},
	"sunset": {
		Name:        "sunset",
		DisplayName: "Sunset",
		Style:       "gradient",
		Colors:      []string{"#FF6B35", "#F7C59F", "#FF006E"},
	},
	"ocean": {
		Name:        "ocean",
		DisplayName: "Ocean",
		Style:       "gradient",
		Colors:      []string{"#0077B6", "#00B4D8", "#90E0EF"},
	},
	"aurora": {
		Name:        "aurora",
		DisplayName: "Aurora",
		Style:       "gradient",
		Colors:      []string{"#9D4EDD", "#5A189A", "#48BFE3"},
	},
	"neon": {
		Name:        "neon",
		DisplayName: "Neon",
		Style:       "gradient",
		Colors:      []string{"#FF00FF", "#00FFFF", "#00FF00"},
	},
	"fire": {
		Name:        "fire",
		DisplayName: "Fire",
		Style:       "gradient",
		Colors:      []string{"#FF4500", "#FF8C00", "#FFD700"},
	},
	"forest": {
		Name:        "forest",
		DisplayName: "Forest",
		Style:       "gradient",
		Colors:      []string{"#2D5016", "#4C8B2F", "#A8E063"},
	},
	"candy": {
		Name:        "candy",
		DisplayName: "Candy",
		Style:       "gradient",
		Colors:      []string{"#FF69B4", "#9370DB", "#40E0D0"},
	},

	"pastel": {
		Name:        "pastel",
		DisplayName: "Pastel",
		Style:       "per-tab",
		Colors:      []string{"#FFB3BA", "#BAFFC9", "#BAE1FF", "#FFFFBA"},
	},
	"jewel": {
		Name:        "jewel",
		DisplayName: "Jewel Tones",
		Style:       "per-tab",
		Colors:      []string{"#9B2335", "#0F4C81", "#5B5EA6", "#9C6644"},
	},
	"terminal": {
		Name:        "terminal",
		DisplayName: "Terminal",
		Style:       "per-tab",
		Colors:      []string{"#FF5555", "#50FA7B", "#8BE9FD", "#F1FA8C"},
	},

	"mono": {
		Name:        "mono",
		DisplayName: "Monochrome",
		Style:       "solid",
		Colors:      []string{},
	},
	"accent": {
		Name:        "accent",
		DisplayName: "Accent",
		Style:       "solid",
		Colors:      []string{},
	},

	"underline": {
		Name:        "underline",
		DisplayName: "Underline",
		Style:       "minimal",
		Colors:      []string{},
	},
	"dim": {
		Name:        "dim",
		DisplayName: "Dim",
		Style:       "minimal",
		Colors:      []string{},
	},
}

TabThemePresets contains all built-in tab theme presets

Functions

func ApplyTheme

func ApplyTheme(name string)

ApplyTheme applies a theme by name, updating all style variables

func ApplyThemeColors

func ApplyThemeColors(theme Theme)

ApplyThemeColors updates all style package variables from a theme.

IMPORTANT: This function is NOT thread-safe for concurrent reads. It must only be called during initialization, before the TUI starts. The TUI's single-threaded Bubble Tea model ensures safe access after init.

func ApplyThemeWithGenericOverrides

func ApplyThemeWithGenericOverrides(name string, overrides map[string]interface{})

ApplyThemeWithGenericOverrides applies a theme with overrides that may include arrays. This supports gradient array overrides from YAML config.

func ApplyThemeWithOverrides

func ApplyThemeWithOverrides(name string, overrides map[string]string)

ApplyThemeWithOverrides applies a theme with color overrides from config

func BgANSISeqFor

func BgANSISeqFor(bgColor lipgloss.Color) string

BgANSISeqFor extracts the raw ANSI escape sequence for the given background color by rendering a marker character and taking everything before it.

func CreateTDModalRenderer

func CreateTDModalRenderer() monitor.ModalRenderer

CreateTDModalRenderer creates a ModalRenderer that uses sidecar's gradient borders. Maps td monitor ModalType and depth values to appropriate gradients from the current theme.

func CreateTDPanelRenderer

func CreateTDPanelRenderer() monitor.PanelRenderer

CreateTDPanelRenderer creates a PanelRenderer that uses sidecar's gradient borders. Maps td monitor PanelState values to appropriate gradients from the current theme.

func FillBackground

func FillBackground(content string, width int, bgColor lipgloss.Color) string

FillBackground ensures each line has a uniform background color. Inner styled elements emit ANSI resets (\x1b[0m) that clear all attributes including the parent container's background, leaving terminal-default black for the remainder of the line. We fix this by re-applying the background ANSI sequence after every reset, then padding short lines with background-colored spaces.

func GetCurrentThemeName

func GetCurrentThemeName() string

GetCurrentThemeName returns the name of the currently active theme

func GetMarkdownTheme

func GetMarkdownTheme() string

GetMarkdownTheme returns the current markdown rendering theme name

func GetSyntaxTheme

func GetSyntaxTheme() string

GetSyntaxTheme returns the current syntax highlighting theme name

func IsValidHexColor

func IsValidHexColor(hex string) bool

IsValidHexColor checks if a string is a valid hex color code (#RRGGBB or #RRGGBBAA)

func IsValidTheme

func IsValidTheme(name string) bool

IsValidTheme checks if a theme name exists in the registry

func ListTabPresets

func ListTabPresets() []string

ListTabPresets returns the names of all available tab presets

func ListThemes

func ListThemes() []string

ListThemes returns the names of all available themes in sorted order

func RGBToHex

func RGBToHex(c RGB) string

RGBToHex converts RGB back to a hex color string.

func RegisterTheme

func RegisterTheme(theme Theme)

RegisterTheme adds a custom theme to the registry

func RenderGradientBorder

func RenderGradientBorder(content string, width, height int, gradient Gradient, padding int) string

RenderGradientBorder renders content inside a box with gradient-colored borders. The gradient flows at the specified angle (typically 30 degrees). width and height are the outer dimensions including borders.

func RenderGradientTab

func RenderGradientTab(label string, tabIndex, totalTabs int, isActive bool) string

RenderGradientTab renders a tab label with a gradient background. Kept for backwards compatibility - delegates to RenderTab.

func RenderPanel

func RenderPanel(content string, width, height int, active bool) string

RenderPanel renders content in a panel with gradient borders. This is the main function plugins should use for bordered panels. active determines whether to use active (focused) or normal gradient. width and height are the outer dimensions including borders.

func RenderPanelWithGradient

func RenderPanelWithGradient(content string, width, height int, gradient Gradient) string

RenderPanelWithGradient renders content in a panel with a custom gradient. Useful for modals or special cases that need different gradient colors.

func RenderPill

func RenderPill(text string, fg, bg, outerBg lipgloss.Color) string

RenderPill renders text with pill-shaped caps when NerdFontsEnabled (PillTabsEnabled) is true. fg is the text color, bg is the pill background, outerBg is the surrounding background. If outerBg is empty, defaults to BgSecondary.

func RenderPillWithStyle

func RenderPillWithStyle(text string, style lipgloss.Style, outerBg lipgloss.Color) string

RenderPillWithStyle renders text with pill-shaped caps using the provided lipgloss.Style. The style's background color is used for the pill caps. outerBg is the surrounding background; if empty, defaults to BgSecondary.

func RenderTab

func RenderTab(label string, tabIndex, totalTabs int, isActive bool, isPreview bool) string

RenderTab renders a tab label using the current tab theme. tabIndex is the 0-based index of this tab, totalTabs is the total count. If isPreview is true, the label is rendered in italic to indicate an ephemeral preview tab.

Types

type ColorPalette

type ColorPalette struct {
	// Brand colors
	Primary   string `json:"primary"`
	Secondary string `json:"secondary"`
	Accent    string `json:"accent"`

	// Status colors
	Success string `json:"success"`
	Warning string `json:"warning"`
	Error   string `json:"error"`
	Info    string `json:"info"`

	// Text colors
	TextPrimary   string `json:"textPrimary"`
	TextSecondary string `json:"textSecondary"`
	TextMuted     string `json:"textMuted"`
	TextSubtle    string `json:"textSubtle"`
	TextSelection string `json:"textSelection"` // Text on selection backgrounds (BgTertiary)

	// Background colors
	BgPrimary   string `json:"bgPrimary"`
	BgSecondary string `json:"bgSecondary"`
	BgTertiary  string `json:"bgTertiary"`
	BgOverlay   string `json:"bgOverlay"`

	// Border colors
	BorderNormal string `json:"borderNormal"`
	BorderActive string `json:"borderActive"`
	BorderMuted  string `json:"borderMuted"`

	// Gradient border colors (for angled gradient borders on panels)
	GradientBorderActive []string `json:"gradientBorderActive"` // Colors for active panel gradient
	GradientBorderNormal []string `json:"gradientBorderNormal"` // Colors for inactive panel gradient
	GradientBorderAngle  float64  `json:"gradientBorderAngle"`  // Angle in degrees (default: 30)

	// Tab theme configuration
	TabStyle  string   `json:"tabStyle"`  // "gradient", "per-tab", "solid", "minimal", or preset name
	TabColors []string `json:"tabColors"` // Color stops for gradient OR per-tab colors

	// Diff colors
	DiffAddFg    string `json:"diffAddFg"`
	DiffAddBg    string `json:"diffAddBg"`
	DiffRemoveFg string `json:"diffRemoveFg"`
	DiffRemoveBg string `json:"diffRemoveBg"`

	// Additional UI colors
	TextHighlight    string `json:"textHighlight"`    // For subtitle, special text
	ButtonHover      string `json:"buttonHover"`      // Button hover state
	TabTextInactive  string `json:"tabTextInactive"`  // Inactive tab text
	Link             string `json:"link"`             // Hyperlink color
	ToastSuccessText string `json:"toastSuccessText"` // Toast success foreground
	ToastErrorText   string `json:"toastErrorText"`   // Toast error foreground

	// Danger button colors (for destructive action buttons)
	DangerLight  string `json:"dangerLight"`  // Light red for danger button text
	DangerDark   string `json:"dangerDark"`   // Dark red for danger button background
	DangerBright string `json:"dangerBright"` // Bright red for focused danger button bg
	DangerHover  string `json:"dangerHover"`  // Darker red for hover danger button bg
	TextInverse  string `json:"textInverse"`  // Inverse text (white on dark themes)

	// Scrollbar colors
	ScrollbarTrack string `json:"scrollbarTrack"` // Track color (default: TextSubtle)
	ScrollbarThumb string `json:"scrollbarThumb"` // Thumb color (default: TextMuted)

	// Blame age gradient colors (newest → oldest)
	BlameAge1 string `json:"blameAge1"` // < 1 week (light green)
	BlameAge2 string `json:"blameAge2"` // < 1 month (lime)
	BlameAge3 string `json:"blameAge3"` // < 3 months (amber)
	BlameAge4 string `json:"blameAge4"` // < 6 months (orange)
	BlameAge5 string `json:"blameAge5"` // < 1 year (gray)

	// Third-party theme names
	SyntaxTheme   string `json:"syntaxTheme"`   // Chroma theme name
	MarkdownTheme string `json:"markdownTheme"` // Glamour theme name
}

ColorPalette holds all theme colors

type Gradient

type Gradient struct {
	Stops []GradientStop
	Angle float64 // degrees (0 = horizontal left-to-right, 90 = vertical top-to-bottom)
}

Gradient defines a multi-stop color gradient with angle support.

func GetActiveGradient

func GetActiveGradient() Gradient

GetActiveGradient returns the gradient for active (focused) panels from current theme.

func GetFlashGradient

func GetFlashGradient() Gradient

GetFlashGradient returns a warning-colored gradient for flash effects.

func GetInteractiveGradient

func GetInteractiveGradient() Gradient

GetInteractiveGradient returns a gradient for interactive mode borders (td-70aed9). Uses warning/success colors to indicate the pane is receiving keyboard input.

func GetNormalGradient

func GetNormalGradient() Gradient

GetNormalGradient returns the gradient for inactive panels from current theme.

func NewGradient

func NewGradient(hexColors []string, angle float64) Gradient

NewGradient creates a gradient from a slice of hex color strings. Colors are evenly distributed from position 0.0 to 1.0.

func (*Gradient) ColorAt

func (g *Gradient) ColorAt(t float64) RGB

ColorAt returns the interpolated color at position t (0.0 to 1.0).

func (*Gradient) IsValid

func (g *Gradient) IsValid() bool

IsValid returns true if the gradient has at least 2 color stops.

func (*Gradient) PositionAt

func (g *Gradient) PositionAt(x, y, width, height int) float64

PositionAt calculates the gradient position for a coordinate given the angle. For a 30-degree angle, the gradient flows diagonally from top-left to bottom-right. Returns a value in range [0, 1].

type GradientStop

type GradientStop struct {
	Position float64
	Color    RGB
}

GradientStop defines a color at a position (0.0 to 1.0)

type RGB

type RGB struct {
	R, G, B float64
}

RGB represents a color in RGB space for interpolation.

func HexToRGB

func HexToRGB(hex string) RGB

HexToRGB converts a hex color string (#RRGGBB) to RGB.

func LerpRGB

func LerpRGB(c1, c2 RGB, t float64) RGB

LerpRGB linearly interpolates between two colors. t should be in range [0, 1] where 0 = c1 and 1 = c2.

func (RGB) ToANSI

func (c RGB) ToANSI() string

ToANSI returns raw ANSI escape code for foreground color.

type TabThemePreset

type TabThemePreset struct {
	Name        string   // Internal name (e.g., "sunset")
	DisplayName string   // Display name (e.g., "Sunset")
	Style       string   // "gradient", "per-tab", "solid", "minimal"
	Colors      []string // Hex colors for gradient stops or per-tab colors
}

TabThemePreset defines a named tab color scheme

func GetTabPreset

func GetTabPreset(name string) *TabThemePreset

GetTabPreset returns a tab theme preset by name, or nil if not found

type Theme

type Theme struct {
	Name        string       `json:"name"`
	DisplayName string       `json:"displayName"`
	Colors      ColorPalette `json:"colors"`
}

Theme represents a complete theme configuration

func GetCurrentTheme

func GetCurrentTheme() Theme

GetCurrentTheme returns the currently active theme

func GetTheme

func GetTheme(name string) Theme

GetTheme returns a theme by name, or the default theme if not found

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL