1package core
2
3import (
4 "image/color"
5 "strings"
6
7 "github.com/charmbracelet/lipgloss/v2"
8 "github.com/charmbracelet/x/ansi"
9 "github.com/opencode-ai/opencode/internal/tui/styles"
10)
11
12func Section(text string, width int) string {
13 t := styles.CurrentTheme()
14 char := "─"
15 length := lipgloss.Width(text) + 1
16 remainingWidth := width - length
17 lineStyle := t.S().Base.Foreground(t.Border)
18 if remainingWidth > 0 {
19 text = text + " " + lineStyle.Render(strings.Repeat(char, remainingWidth))
20 }
21 return text
22}
23
24func Title(title string, width int) string {
25 t := styles.CurrentTheme()
26 char := "╱"
27 length := lipgloss.Width(title) + 1
28 remainingWidth := width - length
29 lineStyle := t.S().Base.Foreground(t.Primary)
30 titleStyle := t.S().Base.Foreground(t.Primary)
31 if remainingWidth > 0 {
32 title = titleStyle.Render(title) + " " + lineStyle.Render(strings.Repeat(char, remainingWidth))
33 }
34 return title
35}
36
37type StatusOpts struct {
38 Icon string
39 IconColor color.Color
40 Title string
41 TitleColor color.Color
42 Description string
43 DescriptionColor color.Color
44}
45
46func Status(ops StatusOpts, width int) string {
47 t := styles.CurrentTheme()
48 icon := "●"
49 iconColor := t.Success
50 if ops.Icon != "" {
51 icon = ops.Icon
52 }
53 if ops.IconColor != nil {
54 iconColor = ops.IconColor
55 }
56 title := ops.Title
57 titleColor := t.FgMuted
58 if ops.TitleColor != nil {
59 titleColor = ops.TitleColor
60 }
61 description := ops.Description
62 descriptionColor := t.FgSubtle
63 if ops.DescriptionColor != nil {
64 descriptionColor = ops.DescriptionColor
65 }
66 icon = t.S().Base.Foreground(iconColor).Render(icon)
67 title = t.S().Base.Foreground(titleColor).Render(title)
68 if description != "" {
69 description = ansi.Truncate(description, width-lipgloss.Width(icon)-lipgloss.Width(title)-2, "…")
70 }
71 description = t.S().Base.Foreground(descriptionColor).Render(description)
72 return strings.Join([]string{
73 icon,
74 title,
75 description,
76 }, " ")
77}