@@ -0,0 +1,194 @@
1+package ui
2+
3+import (
4+ "github.com/charmbracelet/bubbles/v2/filepicker"
5+ "github.com/charmbracelet/bubbles/v2/help"
6+ "github.com/charmbracelet/bubbles/v2/textarea"
7+ "github.com/charmbracelet/bubbles/v2/textinput"
8+ "github.com/charmbracelet/crush/internal/tui/exp/diffview"
9+ "github.com/charmbracelet/glamour/v2/ansi"
10+ "github.com/charmbracelet/lipgloss/v2"
11+ "github.com/charmbracelet/x/exp/charmtone"
12+)
13+
14+const (
15+ CheckIcon string = "✓"
16+ ErrorIcon string = "×"
17+ WarningIcon string = "⚠"
18+ InfoIcon string = "ⓘ"
19+ HintIcon string = "∵"
20+ SpinnerIcon string = "..."
21+ LoadingIcon string = "⟳"
22+ DocumentIcon string = "🖼"
23+ ModelIcon string = "◇"
24+
25+ ToolPending string = "●"
26+ ToolSuccess string = "✓"
27+ ToolError string = "×"
28+
29+ BorderThin string = "│"
30+ BorderThick string = "▌"
31+)
32+
33+type Styles struct {
34+ WindowTooSmall lipgloss.Style
35+
36+ // Reusable text styles
37+ Base lipgloss.Style
38+ Muted lipgloss.Style
39+ Subtle lipgloss.Style
40+
41+ // Tags
42+ TagBase lipgloss.Style
43+ TagError lipgloss.Style
44+ TagInfo lipgloss.Style
45+
46+ // Headers
47+ HeaderTool lipgloss.Style
48+ HeaderToolNested lipgloss.Style
49+
50+ // Panels
51+ PanelMuted lipgloss.Style
52+ PanelBase lipgloss.Style
53+
54+ // Line numbers for code blocks
55+ LineNumber lipgloss.Style
56+
57+ // Message borders
58+ FocusedMessageBorder lipgloss.Border
59+
60+ // Tool calls
61+ ToolCallPending lipgloss.Style
62+ ToolCallError lipgloss.Style
63+ ToolCallSuccess lipgloss.Style
64+ ToolCallCancelled lipgloss.Style
65+ EarlyStateMessage lipgloss.Style
66+
67+ // Text selection
68+ TextSelection lipgloss.Style
69+
70+ // LSP and MCP status indicators
71+ ItemOfflineIcon lipgloss.Style
72+ ItemBusyIcon lipgloss.Style
73+ ItemErrorIcon lipgloss.Style
74+ ItemOnlineIcon lipgloss.Style
75+
76+ // Markdown & Chroma
77+ Markdown ansi.StyleConfig
78+
79+ // Inputs
80+ TextInput textinput.Styles
81+ TextArea textarea.Styles
82+
83+ // Help
84+ Help help.Styles
85+
86+ // Diff
87+ Diff diffview.Style
88+
89+ // FilePicker
90+ FilePicker filepicker.Styles
91+
92+ // Buttons
93+ ButtonSelected lipgloss.Style
94+ ButtonUnselected lipgloss.Style
95+
96+ // Borders
97+ BorderFocus lipgloss.Style
98+ BorderBlur lipgloss.Style
99+}
100+
101+func DefaultStyles() Styles {
102+ var (
103+ // primary = charmtone.Charple
104+ secondary = charmtone.Dolly
105+ // tertiary = charmtone.Bok
106+ // accent = charmtone.Zest
107+
108+ // Backgrounds
109+ bgBase = charmtone.Pepper
110+ bgBaseLighter = charmtone.BBQ
111+ bgSubtle = charmtone.Charcoal
112+ // bgOverlay = charmtone.Iron
113+
114+ // Foregrounds
115+ fgBase = charmtone.Ash
116+ fgMuted = charmtone.Squid
117+ fgHalfMuted = charmtone.Smoke
118+ fgSubtle = charmtone.Oyster
119+ // fgSelected = charmtone.Salt
120+
121+ // Borders
122+ // border = charmtone.Charcoal
123+ borderFocus = charmtone.Charple
124+
125+ // Status
126+ // success = charmtone.Guac
127+ // error = charmtone.Sriracha
128+ // warning = charmtone.Zest
129+ // info = charmtone.Malibu
130+
131+ // Colors
132+ white = charmtone.Butter
133+
134+ blueLight = charmtone.Sardine
135+ blue = charmtone.Malibu
136+
137+ // yellow = charmtone.Mustard
138+ // citron = charmtone.Citron
139+
140+ green = charmtone.Julep
141+ greenDark = charmtone.Guac
142+ // greenLight = charmtone.Bok
143+
144+ // red = charmtone.Coral
145+ redDark = charmtone.Sriracha
146+ // redLight = charmtone.Salmon
147+ // cherry = charmtone.Cherry
148+ )
149+
150+ s := Styles{}
151+
152+ // borders
153+ s.FocusedMessageBorder = lipgloss.Border{Left: BorderThick}
154+
155+ // text presets
156+ s.Base = lipgloss.NewStyle().Foreground(fgBase)
157+ s.Muted = lipgloss.NewStyle().Foreground(fgMuted)
158+ s.Subtle = lipgloss.NewStyle().Foreground(fgSubtle)
159+
160+ s.WindowTooSmall = s.Muted
161+
162+ // tag presets
163+ s.TagBase = lipgloss.NewStyle().Padding(0, 1).Foreground(white)
164+ s.TagError = s.TagBase.Background(redDark)
165+ s.TagInfo = s.TagBase.Background(blueLight)
166+
167+ // headers
168+ s.HeaderTool = lipgloss.NewStyle().Foreground(blue)
169+ s.HeaderToolNested = lipgloss.NewStyle().Foreground(fgHalfMuted)
170+
171+ // panels
172+ s.PanelMuted = s.Muted.Background(bgBaseLighter)
173+ s.PanelBase = lipgloss.NewStyle().Background(bgBase)
174+
175+ // code line number
176+ s.LineNumber = lipgloss.NewStyle().Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
177+
178+ // Tool calls
179+ s.ToolCallPending = lipgloss.NewStyle().Foreground(greenDark).SetString(ToolPending)
180+ s.ToolCallError = lipgloss.NewStyle().Foreground(redDark).SetString(ToolError)
181+ s.ToolCallSuccess = lipgloss.NewStyle().Foreground(green).SetString(ToolSuccess)
182+ // Cancelled uses muted tone but same glyph as pending
183+ s.ToolCallCancelled = s.Muted.SetString(ToolPending)
184+ s.EarlyStateMessage = s.Subtle.PaddingLeft(2)
185+
186+ // Buttons
187+ s.ButtonSelected = lipgloss.NewStyle().Foreground(white).Background(secondary)
188+ s.ButtonUnselected = s.Base.Background(bgSubtle)
189+
190+ // Borders
191+ s.BorderFocus = lipgloss.NewStyle().BorderForeground(borderFocus).Border(lipgloss.RoundedBorder()).Padding(1, 2)
192+
193+ return s
194+}