1package styles
2
3import (
4 "image/color"
5
6 "charm.land/bubbles/v2/filepicker"
7 "charm.land/bubbles/v2/help"
8 "charm.land/bubbles/v2/textarea"
9 "charm.land/bubbles/v2/textinput"
10 tea "charm.land/bubbletea/v2"
11 "charm.land/glamour/v2/ansi"
12 "charm.land/lipgloss/v2"
13 "github.com/alecthomas/chroma/v2"
14 "github.com/charmbracelet/crush/internal/tui/exp/diffview"
15 "github.com/charmbracelet/x/exp/charmtone"
16)
17
18const (
19 CheckIcon string = "β"
20 ErrorIcon string = "Γ"
21 WarningIcon string = "β "
22 InfoIcon string = "β"
23 HintIcon string = "β΅"
24 SpinnerIcon string = "..."
25 LoadingIcon string = "β³"
26 ModelIcon string = "β"
27
28 ArrowRightIcon string = "β"
29
30 ToolPending string = "β"
31 ToolSuccess string = "β"
32 ToolError string = "Γ"
33
34 RadioOn string = "β"
35 RadioOff string = "β"
36
37 BorderThin string = "β"
38 BorderThick string = "β"
39
40 SectionSeparator string = "β"
41
42 TodoCompletedIcon string = "β"
43 TodoPendingIcon string = "β’"
44 TodoInProgressIcon string = "β"
45
46 ImageIcon string = "β "
47 TextIcon string = "β‘"
48
49 ScrollbarThumb string = "β"
50 ScrollbarTrack string = "β"
51)
52
53const (
54 defaultMargin = 2
55 defaultListIndent = 2
56)
57
58type Styles struct {
59 WindowTooSmall lipgloss.Style
60
61 // Reusable text styles
62 Base lipgloss.Style
63 Muted lipgloss.Style
64 HalfMuted lipgloss.Style
65 Subtle lipgloss.Style
66
67 // Tags
68 TagBase lipgloss.Style
69 TagError lipgloss.Style
70 TagInfo lipgloss.Style
71
72 // Header
73 Header struct {
74 Charm lipgloss.Style // Style for "Charmβ’" label
75 Diagonals lipgloss.Style // Style for diagonal separators (β±)
76 Percentage lipgloss.Style // Style for context percentage
77 Keystroke lipgloss.Style // Style for keystroke hints (e.g., "ctrl+d")
78 KeystrokeTip lipgloss.Style // Style for keystroke action text (e.g., "open", "close")
79 WorkingDir lipgloss.Style // Style for current working directory
80 Separator lipgloss.Style // Style for separator dots (β’)
81 }
82
83 CompactDetails struct {
84 View lipgloss.Style
85 Version lipgloss.Style
86 Title lipgloss.Style
87 }
88
89 // Panels
90 PanelMuted lipgloss.Style
91 PanelBase lipgloss.Style
92
93 // Line numbers for code blocks
94 LineNumber lipgloss.Style
95
96 // Message borders
97 FocusedMessageBorder lipgloss.Border
98
99 // Tool calls
100 ToolCallPending lipgloss.Style
101 ToolCallError lipgloss.Style
102 ToolCallSuccess lipgloss.Style
103 ToolCallCancelled lipgloss.Style
104 EarlyStateMessage lipgloss.Style
105
106 // Text selection
107 TextSelection lipgloss.Style
108
109 // LSP and MCP status indicators
110 ItemOfflineIcon lipgloss.Style
111 ItemBusyIcon lipgloss.Style
112 ItemErrorIcon lipgloss.Style
113 ItemOnlineIcon lipgloss.Style
114
115 // Markdown & Chroma
116 Markdown ansi.StyleConfig
117 PlainMarkdown ansi.StyleConfig
118
119 // Inputs
120 TextInput textinput.Styles
121 TextArea textarea.Styles
122
123 // Help
124 Help help.Styles
125
126 // Diff
127 Diff diffview.Style
128
129 // FilePicker
130 FilePicker filepicker.Styles
131
132 // Buttons
133 ButtonFocus lipgloss.Style
134 ButtonBlur lipgloss.Style
135
136 // Borders
137 BorderFocus lipgloss.Style
138 BorderBlur lipgloss.Style
139
140 // Editor
141 EditorPromptNormalFocused lipgloss.Style
142 EditorPromptNormalBlurred lipgloss.Style
143 EditorPromptYoloIconFocused lipgloss.Style
144 EditorPromptYoloIconBlurred lipgloss.Style
145 EditorPromptYoloDotsFocused lipgloss.Style
146 EditorPromptYoloDotsBlurred lipgloss.Style
147
148 // Radio
149 RadioOn lipgloss.Style
150 RadioOff lipgloss.Style
151
152 // Background
153 Background color.Color
154
155 // Logo
156 LogoFieldColor color.Color
157 LogoTitleColorA color.Color
158 LogoTitleColorB color.Color
159 LogoCharmColor color.Color
160 LogoVersionColor color.Color
161
162 // Colors - semantic colors for tool rendering.
163 Primary color.Color
164 Secondary color.Color
165 Tertiary color.Color
166 BgBase color.Color
167 BgBaseLighter color.Color
168 BgSubtle color.Color
169 BgOverlay color.Color
170 FgBase color.Color
171 FgMuted color.Color
172 FgHalfMuted color.Color
173 FgSubtle color.Color
174 Border color.Color
175 BorderColor color.Color // Border focus color
176 Warning color.Color
177 Info color.Color
178 White color.Color
179 BlueLight color.Color
180 Blue color.Color
181 BlueDark color.Color
182 Green color.Color
183 GreenDark color.Color
184 Red color.Color
185 RedDark color.Color
186 Yellow color.Color
187
188 // Section Title
189 Section struct {
190 Title lipgloss.Style
191 Line lipgloss.Style
192 }
193
194 // Initialize
195 Initialize struct {
196 Header lipgloss.Style
197 Content lipgloss.Style
198 Accent lipgloss.Style
199 }
200
201 // LSP
202 LSP struct {
203 ErrorDiagnostic lipgloss.Style
204 WarningDiagnostic lipgloss.Style
205 HintDiagnostic lipgloss.Style
206 InfoDiagnostic lipgloss.Style
207 }
208
209 // Files
210 Files struct {
211 Path lipgloss.Style
212 Additions lipgloss.Style
213 Deletions lipgloss.Style
214 }
215
216 // Chat
217 Chat struct {
218 // Message item styles
219 Message struct {
220 UserBlurred lipgloss.Style
221 UserFocused lipgloss.Style
222 AssistantBlurred lipgloss.Style
223 AssistantFocused lipgloss.Style
224 NoContent lipgloss.Style
225 Thinking lipgloss.Style
226 ErrorTag lipgloss.Style
227 ErrorTitle lipgloss.Style
228 ErrorDetails lipgloss.Style
229 ToolCallFocused lipgloss.Style
230 ToolCallCompact lipgloss.Style
231 ToolCallBlurred lipgloss.Style
232 SectionHeader lipgloss.Style
233
234 // Thinking section styles
235 ThinkingBox lipgloss.Style // Background for thinking content
236 ThinkingTruncationHint lipgloss.Style // "β¦ (N lines hidden)" hint
237 ThinkingFooterTitle lipgloss.Style // "Thought for" text
238 ThinkingFooterDuration lipgloss.Style // Duration value
239 }
240 }
241
242 // Tool - styles for tool call rendering
243 Tool struct {
244 // Icon styles with tool status
245 IconPending lipgloss.Style // Pending operation icon
246 IconSuccess lipgloss.Style // Successful operation icon
247 IconError lipgloss.Style // Error operation icon
248 IconCancelled lipgloss.Style // Cancelled operation icon
249
250 // Tool name styles
251 NameNormal lipgloss.Style // Normal tool name
252 NameNested lipgloss.Style // Nested tool name
253
254 // Parameter list styles
255 ParamMain lipgloss.Style // Main parameter
256 ParamKey lipgloss.Style // Parameter keys
257
258 // Content rendering styles
259 ContentLine lipgloss.Style // Individual content line with background and width
260 ContentTruncation lipgloss.Style // Truncation message "β¦ (N lines)"
261 ContentCodeLine lipgloss.Style // Code line with background and width
262 ContentCodeTruncation lipgloss.Style // Code truncation message with bgBase
263 ContentCodeBg color.Color // Background color for syntax highlighting
264 Body lipgloss.Style // Body content padding (PaddingLeft(2))
265
266 // Deprecated - kept for backward compatibility
267 ContentBg lipgloss.Style // Content background
268 ContentText lipgloss.Style // Content text
269 ContentLineNumber lipgloss.Style // Line numbers in code
270
271 // State message styles
272 StateWaiting lipgloss.Style // "Waiting for tool response..."
273 StateCancelled lipgloss.Style // "Canceled."
274
275 // Error styles
276 ErrorTag lipgloss.Style // ERROR tag
277 ErrorMessage lipgloss.Style // Error message text
278
279 // Diff styles
280 DiffTruncation lipgloss.Style // Diff truncation message with padding
281
282 // Multi-edit note styles
283 NoteTag lipgloss.Style // NOTE tag (yellow background)
284 NoteMessage lipgloss.Style // Note message text
285
286 // Job header styles (for bash jobs)
287 JobIconPending lipgloss.Style // Pending job icon (green dark)
288 JobIconError lipgloss.Style // Error job icon (red dark)
289 JobIconSuccess lipgloss.Style // Success job icon (green)
290 JobToolName lipgloss.Style // Job tool name "Bash" (blue)
291 JobAction lipgloss.Style // Action text (Start, Output, Kill)
292 JobPID lipgloss.Style // PID text
293 JobDescription lipgloss.Style // Description text
294
295 // Agent task styles
296 AgentTaskTag lipgloss.Style // Agent task tag (blue background, bold)
297 AgentPrompt lipgloss.Style // Agent prompt text
298
299 // Agentic fetch styles
300 AgenticFetchPromptTag lipgloss.Style // Agentic fetch prompt tag (green background, bold)
301
302 // Todo styles
303 TodoRatio lipgloss.Style // Todo ratio (e.g., "2/5")
304 TodoCompletedIcon lipgloss.Style // Completed todo icon
305 TodoInProgressIcon lipgloss.Style // In-progress todo icon
306 TodoPendingIcon lipgloss.Style // Pending todo icon
307 }
308
309 // Dialog styles
310 Dialog struct {
311 Title lipgloss.Style
312 TitleText lipgloss.Style
313 TitleError lipgloss.Style
314 TitleAccent lipgloss.Style
315 // View is the main content area style.
316 View lipgloss.Style
317 PrimaryText lipgloss.Style
318 SecondaryText lipgloss.Style
319 // HelpView is the line that contains the help.
320 HelpView lipgloss.Style
321 Help struct {
322 Ellipsis lipgloss.Style
323 ShortKey lipgloss.Style
324 ShortDesc lipgloss.Style
325 ShortSeparator lipgloss.Style
326 FullKey lipgloss.Style
327 FullDesc lipgloss.Style
328 FullSeparator lipgloss.Style
329 }
330 NormalItem lipgloss.Style
331 SelectedItem lipgloss.Style
332 InputPrompt lipgloss.Style
333
334 List lipgloss.Style
335
336 Spinner lipgloss.Style
337
338 // ContentPanel is used for content blocks with subtle background.
339 ContentPanel lipgloss.Style
340
341 // Scrollbar styles for scrollable content.
342 ScrollbarThumb lipgloss.Style
343 ScrollbarTrack lipgloss.Style
344
345 // Arguments
346 Arguments struct {
347 Content lipgloss.Style
348 Description lipgloss.Style
349 InputLabelBlurred lipgloss.Style
350 InputLabelFocused lipgloss.Style
351 InputRequiredMarkBlurred lipgloss.Style
352 InputRequiredMarkFocused lipgloss.Style
353 }
354
355 Commands struct{}
356 }
357
358 // Status bar and help
359 Status struct {
360 Help lipgloss.Style
361
362 ErrorIndicator lipgloss.Style
363 WarnIndicator lipgloss.Style
364 InfoIndicator lipgloss.Style
365 UpdateIndicator lipgloss.Style
366 SuccessIndicator lipgloss.Style
367
368 ErrorMessage lipgloss.Style
369 WarnMessage lipgloss.Style
370 InfoMessage lipgloss.Style
371 UpdateMessage lipgloss.Style
372 SuccessMessage lipgloss.Style
373 }
374
375 // Completions popup styles
376 Completions struct {
377 Normal lipgloss.Style
378 Focused lipgloss.Style
379 Match lipgloss.Style
380 }
381
382 // Attachments styles
383 Attachments struct {
384 Normal lipgloss.Style
385 Image lipgloss.Style
386 Text lipgloss.Style
387 Deleting lipgloss.Style
388 }
389}
390
391// ChromaTheme converts the current markdown chroma styles to a chroma
392// StyleEntries map.
393func (s *Styles) ChromaTheme() chroma.StyleEntries {
394 rules := s.Markdown.CodeBlock
395
396 return chroma.StyleEntries{
397 chroma.Text: chromaStyle(rules.Chroma.Text),
398 chroma.Error: chromaStyle(rules.Chroma.Error),
399 chroma.Comment: chromaStyle(rules.Chroma.Comment),
400 chroma.CommentPreproc: chromaStyle(rules.Chroma.CommentPreproc),
401 chroma.Keyword: chromaStyle(rules.Chroma.Keyword),
402 chroma.KeywordReserved: chromaStyle(rules.Chroma.KeywordReserved),
403 chroma.KeywordNamespace: chromaStyle(rules.Chroma.KeywordNamespace),
404 chroma.KeywordType: chromaStyle(rules.Chroma.KeywordType),
405 chroma.Operator: chromaStyle(rules.Chroma.Operator),
406 chroma.Punctuation: chromaStyle(rules.Chroma.Punctuation),
407 chroma.Name: chromaStyle(rules.Chroma.Name),
408 chroma.NameBuiltin: chromaStyle(rules.Chroma.NameBuiltin),
409 chroma.NameTag: chromaStyle(rules.Chroma.NameTag),
410 chroma.NameAttribute: chromaStyle(rules.Chroma.NameAttribute),
411 chroma.NameClass: chromaStyle(rules.Chroma.NameClass),
412 chroma.NameConstant: chromaStyle(rules.Chroma.NameConstant),
413 chroma.NameDecorator: chromaStyle(rules.Chroma.NameDecorator),
414 chroma.NameException: chromaStyle(rules.Chroma.NameException),
415 chroma.NameFunction: chromaStyle(rules.Chroma.NameFunction),
416 chroma.NameOther: chromaStyle(rules.Chroma.NameOther),
417 chroma.Literal: chromaStyle(rules.Chroma.Literal),
418 chroma.LiteralNumber: chromaStyle(rules.Chroma.LiteralNumber),
419 chroma.LiteralDate: chromaStyle(rules.Chroma.LiteralDate),
420 chroma.LiteralString: chromaStyle(rules.Chroma.LiteralString),
421 chroma.LiteralStringEscape: chromaStyle(rules.Chroma.LiteralStringEscape),
422 chroma.GenericDeleted: chromaStyle(rules.Chroma.GenericDeleted),
423 chroma.GenericEmph: chromaStyle(rules.Chroma.GenericEmph),
424 chroma.GenericInserted: chromaStyle(rules.Chroma.GenericInserted),
425 chroma.GenericStrong: chromaStyle(rules.Chroma.GenericStrong),
426 chroma.GenericSubheading: chromaStyle(rules.Chroma.GenericSubheading),
427 chroma.Background: chromaStyle(rules.Chroma.Background),
428 }
429}
430
431// DialogHelpStyles returns the styles for dialog help.
432func (s *Styles) DialogHelpStyles() help.Styles {
433 return help.Styles(s.Dialog.Help)
434}
435
436// DefaultStyles returns the default styles for the UI.
437func DefaultStyles() Styles {
438 var (
439 primary = charmtone.Charple
440 secondary = charmtone.Dolly
441 tertiary = charmtone.Bok
442 // accent = charmtone.Zest
443
444 // Backgrounds
445 bgBase = charmtone.Pepper
446 bgBaseLighter = charmtone.BBQ
447 bgSubtle = charmtone.Charcoal
448 bgOverlay = charmtone.Iron
449
450 // Foregrounds
451 fgBase = charmtone.Ash
452 fgMuted = charmtone.Squid
453 fgHalfMuted = charmtone.Smoke
454 fgSubtle = charmtone.Oyster
455 // fgSelected = charmtone.Salt
456
457 // Borders
458 border = charmtone.Charcoal
459 borderFocus = charmtone.Charple
460
461 // Status
462 warning = charmtone.Zest
463 info = charmtone.Malibu
464
465 // Colors
466 white = charmtone.Butter
467
468 blueLight = charmtone.Sardine
469 blue = charmtone.Malibu
470 blueDark = charmtone.Damson
471
472 // yellow = charmtone.Mustard
473 yellow = charmtone.Mustard
474 // citron = charmtone.Citron
475
476 green = charmtone.Julep
477 greenDark = charmtone.Guac
478 // greenLight = charmtone.Bok
479
480 red = charmtone.Coral
481 redDark = charmtone.Sriracha
482 // redLight = charmtone.Salmon
483 // cherry = charmtone.Cherry
484 )
485
486 normalBorder := lipgloss.NormalBorder()
487
488 base := lipgloss.NewStyle().Foreground(fgBase)
489
490 s := Styles{}
491
492 s.Background = bgBase
493
494 // Populate color fields
495 s.Primary = primary
496 s.Secondary = secondary
497 s.Tertiary = tertiary
498 s.BgBase = bgBase
499 s.BgBaseLighter = bgBaseLighter
500 s.BgSubtle = bgSubtle
501 s.BgOverlay = bgOverlay
502 s.FgBase = fgBase
503 s.FgMuted = fgMuted
504 s.FgHalfMuted = fgHalfMuted
505 s.FgSubtle = fgSubtle
506 s.Border = border
507 s.BorderColor = borderFocus
508 s.Warning = warning
509 s.Info = info
510 s.White = white
511 s.BlueLight = blueLight
512 s.Blue = blue
513 s.BlueDark = blueDark
514 s.Green = green
515 s.GreenDark = greenDark
516 s.Red = red
517 s.RedDark = redDark
518 s.Yellow = yellow
519
520 s.TextInput = textinput.Styles{
521 Focused: textinput.StyleState{
522 Text: base,
523 Placeholder: base.Foreground(fgSubtle),
524 Prompt: base.Foreground(tertiary),
525 Suggestion: base.Foreground(fgSubtle),
526 },
527 Blurred: textinput.StyleState{
528 Text: base.Foreground(fgMuted),
529 Placeholder: base.Foreground(fgSubtle),
530 Prompt: base.Foreground(fgMuted),
531 Suggestion: base.Foreground(fgSubtle),
532 },
533 Cursor: textinput.CursorStyle{
534 Color: secondary,
535 Shape: tea.CursorBlock,
536 Blink: true,
537 },
538 }
539
540 s.TextArea = textarea.Styles{
541 Focused: textarea.StyleState{
542 Base: base,
543 Text: base,
544 LineNumber: base.Foreground(fgSubtle),
545 CursorLine: base,
546 CursorLineNumber: base.Foreground(fgSubtle),
547 Placeholder: base.Foreground(fgSubtle),
548 Prompt: base.Foreground(tertiary),
549 },
550 Blurred: textarea.StyleState{
551 Base: base,
552 Text: base.Foreground(fgMuted),
553 LineNumber: base.Foreground(fgMuted),
554 CursorLine: base,
555 CursorLineNumber: base.Foreground(fgMuted),
556 Placeholder: base.Foreground(fgSubtle),
557 Prompt: base.Foreground(fgMuted),
558 },
559 Cursor: textarea.CursorStyle{
560 Color: secondary,
561 Shape: tea.CursorBlock,
562 Blink: true,
563 },
564 }
565
566 s.Markdown = ansi.StyleConfig{
567 Document: ansi.StyleBlock{
568 StylePrimitive: ansi.StylePrimitive{
569 // BlockPrefix: "\n",
570 // BlockSuffix: "\n",
571 Color: stringPtr(charmtone.Smoke.Hex()),
572 },
573 // Margin: uintPtr(defaultMargin),
574 },
575 BlockQuote: ansi.StyleBlock{
576 StylePrimitive: ansi.StylePrimitive{},
577 Indent: uintPtr(1),
578 IndentToken: stringPtr("β "),
579 },
580 List: ansi.StyleList{
581 LevelIndent: defaultListIndent,
582 },
583 Heading: ansi.StyleBlock{
584 StylePrimitive: ansi.StylePrimitive{
585 BlockSuffix: "\n",
586 Color: stringPtr(charmtone.Malibu.Hex()),
587 Bold: boolPtr(true),
588 },
589 },
590 H1: ansi.StyleBlock{
591 StylePrimitive: ansi.StylePrimitive{
592 Prefix: " ",
593 Suffix: " ",
594 Color: stringPtr(charmtone.Zest.Hex()),
595 BackgroundColor: stringPtr(charmtone.Charple.Hex()),
596 Bold: boolPtr(true),
597 },
598 },
599 H2: ansi.StyleBlock{
600 StylePrimitive: ansi.StylePrimitive{
601 Prefix: "## ",
602 },
603 },
604 H3: ansi.StyleBlock{
605 StylePrimitive: ansi.StylePrimitive{
606 Prefix: "### ",
607 },
608 },
609 H4: ansi.StyleBlock{
610 StylePrimitive: ansi.StylePrimitive{
611 Prefix: "#### ",
612 },
613 },
614 H5: ansi.StyleBlock{
615 StylePrimitive: ansi.StylePrimitive{
616 Prefix: "##### ",
617 },
618 },
619 H6: ansi.StyleBlock{
620 StylePrimitive: ansi.StylePrimitive{
621 Prefix: "###### ",
622 Color: stringPtr(charmtone.Guac.Hex()),
623 Bold: boolPtr(false),
624 },
625 },
626 Strikethrough: ansi.StylePrimitive{
627 CrossedOut: boolPtr(true),
628 },
629 Emph: ansi.StylePrimitive{
630 Italic: boolPtr(true),
631 },
632 Strong: ansi.StylePrimitive{
633 Bold: boolPtr(true),
634 },
635 HorizontalRule: ansi.StylePrimitive{
636 Color: stringPtr(charmtone.Charcoal.Hex()),
637 Format: "\n--------\n",
638 },
639 Item: ansi.StylePrimitive{
640 BlockPrefix: "β’ ",
641 },
642 Enumeration: ansi.StylePrimitive{
643 BlockPrefix: ". ",
644 },
645 Task: ansi.StyleTask{
646 StylePrimitive: ansi.StylePrimitive{},
647 Ticked: "[β] ",
648 Unticked: "[ ] ",
649 },
650 Link: ansi.StylePrimitive{
651 Color: stringPtr(charmtone.Zinc.Hex()),
652 Underline: boolPtr(true),
653 },
654 LinkText: ansi.StylePrimitive{
655 Color: stringPtr(charmtone.Guac.Hex()),
656 Bold: boolPtr(true),
657 },
658 Image: ansi.StylePrimitive{
659 Color: stringPtr(charmtone.Cheeky.Hex()),
660 Underline: boolPtr(true),
661 },
662 ImageText: ansi.StylePrimitive{
663 Color: stringPtr(charmtone.Squid.Hex()),
664 Format: "Image: {{.text}} β",
665 },
666 Code: ansi.StyleBlock{
667 StylePrimitive: ansi.StylePrimitive{
668 Prefix: " ",
669 Suffix: " ",
670 Color: stringPtr(charmtone.Coral.Hex()),
671 BackgroundColor: stringPtr(charmtone.Charcoal.Hex()),
672 },
673 },
674 CodeBlock: ansi.StyleCodeBlock{
675 StyleBlock: ansi.StyleBlock{
676 StylePrimitive: ansi.StylePrimitive{
677 Color: stringPtr(charmtone.Charcoal.Hex()),
678 },
679 Margin: uintPtr(defaultMargin),
680 },
681 Chroma: &ansi.Chroma{
682 Text: ansi.StylePrimitive{
683 Color: stringPtr(charmtone.Smoke.Hex()),
684 },
685 Error: ansi.StylePrimitive{
686 Color: stringPtr(charmtone.Butter.Hex()),
687 BackgroundColor: stringPtr(charmtone.Sriracha.Hex()),
688 },
689 Comment: ansi.StylePrimitive{
690 Color: stringPtr(charmtone.Oyster.Hex()),
691 },
692 CommentPreproc: ansi.StylePrimitive{
693 Color: stringPtr(charmtone.Bengal.Hex()),
694 },
695 Keyword: ansi.StylePrimitive{
696 Color: stringPtr(charmtone.Malibu.Hex()),
697 },
698 KeywordReserved: ansi.StylePrimitive{
699 Color: stringPtr(charmtone.Pony.Hex()),
700 },
701 KeywordNamespace: ansi.StylePrimitive{
702 Color: stringPtr(charmtone.Pony.Hex()),
703 },
704 KeywordType: ansi.StylePrimitive{
705 Color: stringPtr(charmtone.Guppy.Hex()),
706 },
707 Operator: ansi.StylePrimitive{
708 Color: stringPtr(charmtone.Salmon.Hex()),
709 },
710 Punctuation: ansi.StylePrimitive{
711 Color: stringPtr(charmtone.Zest.Hex()),
712 },
713 Name: ansi.StylePrimitive{
714 Color: stringPtr(charmtone.Smoke.Hex()),
715 },
716 NameBuiltin: ansi.StylePrimitive{
717 Color: stringPtr(charmtone.Cheeky.Hex()),
718 },
719 NameTag: ansi.StylePrimitive{
720 Color: stringPtr(charmtone.Mauve.Hex()),
721 },
722 NameAttribute: ansi.StylePrimitive{
723 Color: stringPtr(charmtone.Hazy.Hex()),
724 },
725 NameClass: ansi.StylePrimitive{
726 Color: stringPtr(charmtone.Salt.Hex()),
727 Underline: boolPtr(true),
728 Bold: boolPtr(true),
729 },
730 NameDecorator: ansi.StylePrimitive{
731 Color: stringPtr(charmtone.Citron.Hex()),
732 },
733 NameFunction: ansi.StylePrimitive{
734 Color: stringPtr(charmtone.Guac.Hex()),
735 },
736 LiteralNumber: ansi.StylePrimitive{
737 Color: stringPtr(charmtone.Julep.Hex()),
738 },
739 LiteralString: ansi.StylePrimitive{
740 Color: stringPtr(charmtone.Cumin.Hex()),
741 },
742 LiteralStringEscape: ansi.StylePrimitive{
743 Color: stringPtr(charmtone.Bok.Hex()),
744 },
745 GenericDeleted: ansi.StylePrimitive{
746 Color: stringPtr(charmtone.Coral.Hex()),
747 },
748 GenericEmph: ansi.StylePrimitive{
749 Italic: boolPtr(true),
750 },
751 GenericInserted: ansi.StylePrimitive{
752 Color: stringPtr(charmtone.Guac.Hex()),
753 },
754 GenericStrong: ansi.StylePrimitive{
755 Bold: boolPtr(true),
756 },
757 GenericSubheading: ansi.StylePrimitive{
758 Color: stringPtr(charmtone.Squid.Hex()),
759 },
760 Background: ansi.StylePrimitive{
761 BackgroundColor: stringPtr(charmtone.Charcoal.Hex()),
762 },
763 },
764 },
765 Table: ansi.StyleTable{
766 StyleBlock: ansi.StyleBlock{
767 StylePrimitive: ansi.StylePrimitive{},
768 },
769 },
770 DefinitionDescription: ansi.StylePrimitive{
771 BlockPrefix: "\n ",
772 },
773 }
774
775 // PlainMarkdown style - muted colors on subtle background for thinking content.
776 plainBg := stringPtr(bgBaseLighter.Hex())
777 plainFg := stringPtr(fgMuted.Hex())
778 s.PlainMarkdown = ansi.StyleConfig{
779 Document: ansi.StyleBlock{
780 StylePrimitive: ansi.StylePrimitive{
781 Color: plainFg,
782 BackgroundColor: plainBg,
783 },
784 },
785 BlockQuote: ansi.StyleBlock{
786 StylePrimitive: ansi.StylePrimitive{
787 Color: plainFg,
788 BackgroundColor: plainBg,
789 },
790 Indent: uintPtr(1),
791 IndentToken: stringPtr("β "),
792 },
793 List: ansi.StyleList{
794 LevelIndent: defaultListIndent,
795 },
796 Heading: ansi.StyleBlock{
797 StylePrimitive: ansi.StylePrimitive{
798 BlockSuffix: "\n",
799 Bold: boolPtr(true),
800 Color: plainFg,
801 BackgroundColor: plainBg,
802 },
803 },
804 H1: ansi.StyleBlock{
805 StylePrimitive: ansi.StylePrimitive{
806 Prefix: " ",
807 Suffix: " ",
808 Bold: boolPtr(true),
809 Color: plainFg,
810 BackgroundColor: plainBg,
811 },
812 },
813 H2: ansi.StyleBlock{
814 StylePrimitive: ansi.StylePrimitive{
815 Prefix: "## ",
816 Color: plainFg,
817 BackgroundColor: plainBg,
818 },
819 },
820 H3: ansi.StyleBlock{
821 StylePrimitive: ansi.StylePrimitive{
822 Prefix: "### ",
823 Color: plainFg,
824 BackgroundColor: plainBg,
825 },
826 },
827 H4: ansi.StyleBlock{
828 StylePrimitive: ansi.StylePrimitive{
829 Prefix: "#### ",
830 Color: plainFg,
831 BackgroundColor: plainBg,
832 },
833 },
834 H5: ansi.StyleBlock{
835 StylePrimitive: ansi.StylePrimitive{
836 Prefix: "##### ",
837 Color: plainFg,
838 BackgroundColor: plainBg,
839 },
840 },
841 H6: ansi.StyleBlock{
842 StylePrimitive: ansi.StylePrimitive{
843 Prefix: "###### ",
844 Color: plainFg,
845 BackgroundColor: plainBg,
846 },
847 },
848 Strikethrough: ansi.StylePrimitive{
849 CrossedOut: boolPtr(true),
850 Color: plainFg,
851 BackgroundColor: plainBg,
852 },
853 Emph: ansi.StylePrimitive{
854 Italic: boolPtr(true),
855 Color: plainFg,
856 BackgroundColor: plainBg,
857 },
858 Strong: ansi.StylePrimitive{
859 Bold: boolPtr(true),
860 Color: plainFg,
861 BackgroundColor: plainBg,
862 },
863 HorizontalRule: ansi.StylePrimitive{
864 Format: "\n--------\n",
865 Color: plainFg,
866 BackgroundColor: plainBg,
867 },
868 Item: ansi.StylePrimitive{
869 BlockPrefix: "β’ ",
870 Color: plainFg,
871 BackgroundColor: plainBg,
872 },
873 Enumeration: ansi.StylePrimitive{
874 BlockPrefix: ". ",
875 Color: plainFg,
876 BackgroundColor: plainBg,
877 },
878 Task: ansi.StyleTask{
879 StylePrimitive: ansi.StylePrimitive{
880 Color: plainFg,
881 BackgroundColor: plainBg,
882 },
883 Ticked: "[β] ",
884 Unticked: "[ ] ",
885 },
886 Link: ansi.StylePrimitive{
887 Underline: boolPtr(true),
888 Color: plainFg,
889 BackgroundColor: plainBg,
890 },
891 LinkText: ansi.StylePrimitive{
892 Bold: boolPtr(true),
893 Color: plainFg,
894 BackgroundColor: plainBg,
895 },
896 Image: ansi.StylePrimitive{
897 Underline: boolPtr(true),
898 Color: plainFg,
899 BackgroundColor: plainBg,
900 },
901 ImageText: ansi.StylePrimitive{
902 Format: "Image: {{.text}} β",
903 Color: plainFg,
904 BackgroundColor: plainBg,
905 },
906 Code: ansi.StyleBlock{
907 StylePrimitive: ansi.StylePrimitive{
908 Prefix: " ",
909 Suffix: " ",
910 Color: plainFg,
911 BackgroundColor: plainBg,
912 },
913 },
914 CodeBlock: ansi.StyleCodeBlock{
915 StyleBlock: ansi.StyleBlock{
916 StylePrimitive: ansi.StylePrimitive{
917 Color: plainFg,
918 BackgroundColor: plainBg,
919 },
920 Margin: uintPtr(defaultMargin),
921 },
922 },
923 Table: ansi.StyleTable{
924 StyleBlock: ansi.StyleBlock{
925 StylePrimitive: ansi.StylePrimitive{
926 Color: plainFg,
927 BackgroundColor: plainBg,
928 },
929 },
930 },
931 DefinitionDescription: ansi.StylePrimitive{
932 BlockPrefix: "\n ",
933 Color: plainFg,
934 BackgroundColor: plainBg,
935 },
936 }
937
938 s.Help = help.Styles{
939 ShortKey: base.Foreground(fgMuted),
940 ShortDesc: base.Foreground(fgSubtle),
941 ShortSeparator: base.Foreground(border),
942 Ellipsis: base.Foreground(border),
943 FullKey: base.Foreground(fgMuted),
944 FullDesc: base.Foreground(fgSubtle),
945 FullSeparator: base.Foreground(border),
946 }
947
948 s.Diff = diffview.Style{
949 DividerLine: diffview.LineStyle{
950 LineNumber: lipgloss.NewStyle().
951 Foreground(fgHalfMuted).
952 Background(bgBaseLighter),
953 Code: lipgloss.NewStyle().
954 Foreground(fgHalfMuted).
955 Background(bgBaseLighter),
956 },
957 MissingLine: diffview.LineStyle{
958 LineNumber: lipgloss.NewStyle().
959 Background(bgBaseLighter),
960 Code: lipgloss.NewStyle().
961 Background(bgBaseLighter),
962 },
963 EqualLine: diffview.LineStyle{
964 LineNumber: lipgloss.NewStyle().
965 Foreground(fgMuted).
966 Background(bgBase),
967 Code: lipgloss.NewStyle().
968 Foreground(fgMuted).
969 Background(bgBase),
970 },
971 InsertLine: diffview.LineStyle{
972 LineNumber: lipgloss.NewStyle().
973 Foreground(lipgloss.Color("#629657")).
974 Background(lipgloss.Color("#2b322a")),
975 Symbol: lipgloss.NewStyle().
976 Foreground(lipgloss.Color("#629657")).
977 Background(lipgloss.Color("#323931")),
978 Code: lipgloss.NewStyle().
979 Background(lipgloss.Color("#323931")),
980 },
981 DeleteLine: diffview.LineStyle{
982 LineNumber: lipgloss.NewStyle().
983 Foreground(lipgloss.Color("#a45c59")).
984 Background(lipgloss.Color("#312929")),
985 Symbol: lipgloss.NewStyle().
986 Foreground(lipgloss.Color("#a45c59")).
987 Background(lipgloss.Color("#383030")),
988 Code: lipgloss.NewStyle().
989 Background(lipgloss.Color("#383030")),
990 },
991 }
992
993 s.FilePicker = filepicker.Styles{
994 DisabledCursor: base.Foreground(fgMuted),
995 Cursor: base.Foreground(fgBase),
996 Symlink: base.Foreground(fgSubtle),
997 Directory: base.Foreground(primary),
998 File: base.Foreground(fgBase),
999 DisabledFile: base.Foreground(fgMuted),
1000 DisabledSelected: base.Background(bgOverlay).Foreground(fgMuted),
1001 Permission: base.Foreground(fgMuted),
1002 Selected: base.Background(primary).Foreground(fgBase),
1003 FileSize: base.Foreground(fgMuted),
1004 EmptyDirectory: base.Foreground(fgMuted).PaddingLeft(2).SetString("Empty directory"),
1005 }
1006
1007 // borders
1008 s.FocusedMessageBorder = lipgloss.Border{Left: BorderThick}
1009
1010 // text presets
1011 s.Base = lipgloss.NewStyle().Foreground(fgBase)
1012 s.Muted = lipgloss.NewStyle().Foreground(fgMuted)
1013 s.HalfMuted = lipgloss.NewStyle().Foreground(fgHalfMuted)
1014 s.Subtle = lipgloss.NewStyle().Foreground(fgSubtle)
1015
1016 s.WindowTooSmall = s.Muted
1017
1018 // tag presets
1019 s.TagBase = lipgloss.NewStyle().Padding(0, 1).Foreground(white)
1020 s.TagError = s.TagBase.Background(redDark)
1021 s.TagInfo = s.TagBase.Background(blueLight)
1022
1023 // Compact header styles
1024 s.Header.Charm = base.Foreground(secondary)
1025 s.Header.Diagonals = base.Foreground(primary)
1026 s.Header.Percentage = s.Muted
1027 s.Header.Keystroke = s.Muted
1028 s.Header.KeystrokeTip = s.Subtle
1029 s.Header.WorkingDir = s.Muted
1030 s.Header.Separator = s.Subtle
1031
1032 s.CompactDetails.Title = s.Base
1033 s.CompactDetails.View = s.Base.Padding(0, 1, 1, 1).Border(lipgloss.RoundedBorder()).BorderForeground(borderFocus)
1034 s.CompactDetails.Version = s.Muted
1035
1036 // panels
1037 s.PanelMuted = s.Muted.Background(bgBaseLighter)
1038 s.PanelBase = lipgloss.NewStyle().Background(bgBase)
1039
1040 // code line number
1041 s.LineNumber = lipgloss.NewStyle().Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
1042
1043 // Tool calls
1044 s.ToolCallPending = lipgloss.NewStyle().Foreground(greenDark).SetString(ToolPending)
1045 s.ToolCallError = lipgloss.NewStyle().Foreground(redDark).SetString(ToolError)
1046 s.ToolCallSuccess = lipgloss.NewStyle().Foreground(green).SetString(ToolSuccess)
1047 // Cancelled uses muted tone but same glyph as pending
1048 s.ToolCallCancelled = s.Muted.SetString(ToolPending)
1049 s.EarlyStateMessage = s.Subtle.PaddingLeft(2)
1050
1051 // Tool rendering styles
1052 s.Tool.IconPending = base.Foreground(greenDark).SetString(ToolPending)
1053 s.Tool.IconSuccess = base.Foreground(green).SetString(ToolSuccess)
1054 s.Tool.IconError = base.Foreground(redDark).SetString(ToolError)
1055 s.Tool.IconCancelled = s.Muted.SetString(ToolPending)
1056
1057 s.Tool.NameNormal = base.Foreground(blue)
1058 s.Tool.NameNested = base.Foreground(fgHalfMuted)
1059
1060 s.Tool.ParamMain = s.Subtle
1061 s.Tool.ParamKey = s.Subtle
1062
1063 // Content rendering - prepared styles that accept width parameter
1064 s.Tool.ContentLine = s.Muted.Background(bgBaseLighter)
1065 s.Tool.ContentTruncation = s.Muted.Background(bgBaseLighter)
1066 s.Tool.ContentCodeLine = s.Base.Background(bgBase)
1067 s.Tool.ContentCodeTruncation = s.Muted.Background(bgBase).PaddingLeft(2)
1068 s.Tool.ContentCodeBg = bgBase
1069 s.Tool.Body = base.PaddingLeft(2)
1070
1071 // Deprecated - kept for backward compatibility
1072 s.Tool.ContentBg = s.Muted.Background(bgBaseLighter)
1073 s.Tool.ContentText = s.Muted
1074 s.Tool.ContentLineNumber = base.Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
1075
1076 s.Tool.StateWaiting = base.Foreground(fgSubtle)
1077 s.Tool.StateCancelled = base.Foreground(fgSubtle)
1078
1079 s.Tool.ErrorTag = base.Padding(0, 1).Background(red).Foreground(white)
1080 s.Tool.ErrorMessage = base.Foreground(fgHalfMuted)
1081
1082 // Diff and multi-edit styles
1083 s.Tool.DiffTruncation = s.Muted.Background(bgBaseLighter).PaddingLeft(2)
1084 s.Tool.NoteTag = base.Padding(0, 1).Background(info).Foreground(white)
1085 s.Tool.NoteMessage = base.Foreground(fgHalfMuted)
1086
1087 // Job header styles
1088 s.Tool.JobIconPending = base.Foreground(greenDark)
1089 s.Tool.JobIconError = base.Foreground(redDark)
1090 s.Tool.JobIconSuccess = base.Foreground(green)
1091 s.Tool.JobToolName = base.Foreground(blue)
1092 s.Tool.JobAction = base.Foreground(blueDark)
1093 s.Tool.JobPID = s.Muted
1094 s.Tool.JobDescription = s.Subtle
1095
1096 // Agent task styles
1097 s.Tool.AgentTaskTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(blueLight).Foreground(white)
1098 s.Tool.AgentPrompt = s.Muted
1099
1100 // Agentic fetch styles
1101 s.Tool.AgenticFetchPromptTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(green).Foreground(border)
1102
1103 // Todo styles
1104 s.Tool.TodoRatio = base.Foreground(blueDark)
1105 s.Tool.TodoCompletedIcon = base.Foreground(green)
1106 s.Tool.TodoInProgressIcon = base.Foreground(greenDark)
1107 s.Tool.TodoPendingIcon = base.Foreground(fgMuted)
1108
1109 // Buttons
1110 s.ButtonFocus = lipgloss.NewStyle().Foreground(white).Background(secondary)
1111 s.ButtonBlur = s.Base.Background(bgSubtle)
1112
1113 // Borders
1114 s.BorderFocus = lipgloss.NewStyle().BorderForeground(borderFocus).Border(lipgloss.RoundedBorder()).Padding(1, 2)
1115
1116 // Editor
1117 s.EditorPromptNormalFocused = lipgloss.NewStyle().Foreground(greenDark).SetString("::: ")
1118 s.EditorPromptNormalBlurred = s.EditorPromptNormalFocused.Foreground(fgMuted)
1119 s.EditorPromptYoloIconFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Oyster).Background(charmtone.Citron).Bold(true).SetString(" ! ")
1120 s.EditorPromptYoloIconBlurred = s.EditorPromptYoloIconFocused.Foreground(charmtone.Pepper).Background(charmtone.Squid)
1121 s.EditorPromptYoloDotsFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Zest).SetString(":::")
1122 s.EditorPromptYoloDotsBlurred = s.EditorPromptYoloDotsFocused.Foreground(charmtone.Squid)
1123
1124 s.RadioOn = s.HalfMuted.SetString(RadioOn)
1125 s.RadioOff = s.HalfMuted.SetString(RadioOff)
1126
1127 // Logo colors
1128 s.LogoFieldColor = primary
1129 s.LogoTitleColorA = secondary
1130 s.LogoTitleColorB = primary
1131 s.LogoCharmColor = secondary
1132 s.LogoVersionColor = primary
1133
1134 // Section
1135 s.Section.Title = s.Subtle
1136 s.Section.Line = s.Base.Foreground(charmtone.Charcoal)
1137
1138 // Initialize
1139 s.Initialize.Header = s.Base
1140 s.Initialize.Content = s.Muted
1141 s.Initialize.Accent = s.Base.Foreground(greenDark)
1142
1143 // LSP and MCP status.
1144 s.ItemOfflineIcon = lipgloss.NewStyle().Foreground(charmtone.Squid).SetString("β")
1145 s.ItemBusyIcon = s.ItemOfflineIcon.Foreground(charmtone.Citron)
1146 s.ItemErrorIcon = s.ItemOfflineIcon.Foreground(charmtone.Coral)
1147 s.ItemOnlineIcon = s.ItemOfflineIcon.Foreground(charmtone.Guac)
1148
1149 // LSP
1150 s.LSP.ErrorDiagnostic = s.Base.Foreground(redDark)
1151 s.LSP.WarningDiagnostic = s.Base.Foreground(warning)
1152 s.LSP.HintDiagnostic = s.Base.Foreground(fgHalfMuted)
1153 s.LSP.InfoDiagnostic = s.Base.Foreground(info)
1154
1155 // Files
1156 s.Files.Path = s.Muted
1157 s.Files.Additions = s.Base.Foreground(greenDark)
1158 s.Files.Deletions = s.Base.Foreground(redDark)
1159
1160 // Chat
1161 messageFocussedBorder := lipgloss.Border{
1162 Left: "β",
1163 }
1164
1165 s.Chat.Message.NoContent = lipgloss.NewStyle().Foreground(fgBase)
1166 s.Chat.Message.UserBlurred = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1167 BorderForeground(primary).BorderStyle(normalBorder)
1168 s.Chat.Message.UserFocused = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1169 BorderForeground(primary).BorderStyle(messageFocussedBorder)
1170 s.Chat.Message.AssistantBlurred = s.Chat.Message.NoContent.PaddingLeft(2)
1171 s.Chat.Message.AssistantFocused = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1172 BorderForeground(greenDark).BorderStyle(messageFocussedBorder)
1173 s.Chat.Message.Thinking = lipgloss.NewStyle().MaxHeight(10)
1174 s.Chat.Message.ErrorTag = lipgloss.NewStyle().Padding(0, 1).
1175 Background(red).Foreground(white)
1176 s.Chat.Message.ErrorTitle = lipgloss.NewStyle().Foreground(fgHalfMuted)
1177 s.Chat.Message.ErrorDetails = lipgloss.NewStyle().Foreground(fgSubtle)
1178
1179 // Message item styles
1180 s.Chat.Message.ToolCallFocused = s.Muted.PaddingLeft(1).
1181 BorderStyle(messageFocussedBorder).
1182 BorderLeft(true).
1183 BorderForeground(greenDark)
1184 s.Chat.Message.ToolCallBlurred = s.Muted.PaddingLeft(2)
1185 // No padding or border for compact tool calls within messages
1186 s.Chat.Message.ToolCallCompact = s.Muted
1187 s.Chat.Message.SectionHeader = s.Base.PaddingLeft(2)
1188
1189 // Thinking section styles
1190 s.Chat.Message.ThinkingBox = s.Subtle.Background(bgBaseLighter)
1191 s.Chat.Message.ThinkingTruncationHint = s.Muted
1192 s.Chat.Message.ThinkingFooterTitle = s.Muted
1193 s.Chat.Message.ThinkingFooterDuration = s.Subtle
1194
1195 // Text selection.
1196 s.TextSelection = lipgloss.NewStyle().Foreground(charmtone.Salt).Background(charmtone.Charple)
1197
1198 // Dialog styles
1199 s.Dialog.Title = base.Padding(0, 1).Foreground(primary)
1200 s.Dialog.TitleText = base.Foreground(primary)
1201 s.Dialog.TitleError = base.Foreground(red)
1202 s.Dialog.TitleAccent = base.Foreground(green).Bold(true)
1203 s.Dialog.View = base.Border(lipgloss.RoundedBorder()).BorderForeground(borderFocus)
1204 s.Dialog.PrimaryText = base.Padding(0, 1).Foreground(primary)
1205 s.Dialog.SecondaryText = base.Padding(0, 1).Foreground(fgSubtle)
1206 s.Dialog.HelpView = base.Padding(0, 1).AlignHorizontal(lipgloss.Left)
1207 s.Dialog.Help.ShortKey = base.Foreground(fgMuted)
1208 s.Dialog.Help.ShortDesc = base.Foreground(fgSubtle)
1209 s.Dialog.Help.ShortSeparator = base.Foreground(border)
1210 s.Dialog.Help.Ellipsis = base.Foreground(border)
1211 s.Dialog.Help.FullKey = base.Foreground(fgMuted)
1212 s.Dialog.Help.FullDesc = base.Foreground(fgSubtle)
1213 s.Dialog.Help.FullSeparator = base.Foreground(border)
1214 s.Dialog.NormalItem = base.Padding(0, 1).Foreground(fgBase)
1215 s.Dialog.SelectedItem = base.Padding(0, 1).Background(primary).Foreground(fgBase)
1216 s.Dialog.InputPrompt = base.Margin(1, 1)
1217
1218 s.Dialog.List = base.Margin(0, 0, 1, 0)
1219 s.Dialog.ContentPanel = base.Background(bgSubtle).Foreground(fgBase).Padding(1, 2)
1220 s.Dialog.Spinner = base.Foreground(secondary)
1221 s.Dialog.ScrollbarThumb = base.Foreground(secondary)
1222 s.Dialog.ScrollbarTrack = base.Foreground(border)
1223
1224 s.Dialog.Arguments.Content = base.Padding(1)
1225 s.Dialog.Arguments.Description = base.MarginBottom(1).MaxHeight(3)
1226 s.Dialog.Arguments.InputLabelBlurred = base.Foreground(fgMuted)
1227 s.Dialog.Arguments.InputLabelFocused = base.Bold(true)
1228 s.Dialog.Arguments.InputRequiredMarkBlurred = base.Foreground(fgMuted).SetString("*")
1229 s.Dialog.Arguments.InputRequiredMarkFocused = base.Foreground(primary).Bold(true).SetString("*")
1230
1231 s.Status.Help = lipgloss.NewStyle().Padding(0, 1)
1232 s.Status.SuccessIndicator = base.Foreground(bgSubtle).Background(green).Padding(0, 1).Bold(true).SetString("OKAY!")
1233 s.Status.InfoIndicator = s.Status.SuccessIndicator
1234 s.Status.UpdateIndicator = s.Status.SuccessIndicator.SetString("HEY!")
1235 s.Status.WarnIndicator = s.Status.SuccessIndicator.Foreground(bgOverlay).Background(yellow).SetString("WARNING")
1236 s.Status.ErrorIndicator = s.Status.SuccessIndicator.Foreground(bgBase).Background(red).SetString("ERROR")
1237 s.Status.SuccessMessage = base.Foreground(bgSubtle).Background(greenDark).Padding(0, 1)
1238 s.Status.InfoMessage = s.Status.SuccessMessage
1239 s.Status.UpdateMessage = s.Status.SuccessMessage
1240 s.Status.WarnMessage = s.Status.SuccessMessage.Foreground(bgOverlay).Background(warning)
1241 s.Status.ErrorMessage = s.Status.SuccessMessage.Foreground(white).Background(redDark)
1242
1243 // Completions styles
1244 s.Completions.Normal = base.Background(bgSubtle).Foreground(fgBase)
1245 s.Completions.Focused = base.Background(primary).Foreground(white)
1246 s.Completions.Match = base.Underline(true)
1247
1248 // Attachments styles
1249 attachmentIconStyle := base.Foreground(bgSubtle).Background(green).Padding(0, 1)
1250 s.Attachments.Image = attachmentIconStyle.SetString(ImageIcon)
1251 s.Attachments.Text = attachmentIconStyle.SetString(TextIcon)
1252 s.Attachments.Normal = base.Padding(0, 1).MarginRight(1).Background(fgMuted).Foreground(fgBase)
1253 s.Attachments.Deleting = base.Padding(0, 1).Bold(true).Background(red).Foreground(fgBase)
1254
1255 return s
1256}
1257
1258// Helper functions for style pointers
1259func boolPtr(b bool) *bool { return &b }
1260func stringPtr(s string) *string { return &s }
1261func uintPtr(u uint) *uint { return &u }
1262func chromaStyle(style ansi.StylePrimitive) string {
1263 var s string
1264
1265 if style.Color != nil {
1266 s = *style.Color
1267 }
1268 if style.BackgroundColor != nil {
1269 if s != "" {
1270 s += " "
1271 }
1272 s += "bg:" + *style.BackgroundColor
1273 }
1274 if style.Italic != nil && *style.Italic {
1275 if s != "" {
1276 s += " "
1277 }
1278 s += "italic"
1279 }
1280 if style.Bold != nil && *style.Bold {
1281 if s != "" {
1282 s += " "
1283 }
1284 s += "bold"
1285 }
1286 if style.Underline != nil && *style.Underline {
1287 if s != "" {
1288 s += " "
1289 }
1290 s += "underline"
1291 }
1292
1293 return s
1294}