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 := len(text) + 1
16 remainingWidth := width - length
17 if remainingWidth > 0 {
18 text = text + " " + t.S().Base.Foreground(t.Border).Render(strings.Repeat(char, remainingWidth))
19 }
20 return text
21}
22
23func Title(title string, width int) string {
24 t := styles.CurrentTheme()
25 char := "╱"
26 length := len(title) + 1
27 remainingWidth := width - length
28 lineStyle := t.S().Base.Foreground(t.Primary)
29 titleStyle := t.S().Base.Foreground(t.Primary)
30 if remainingWidth > 0 {
31 title = titleStyle.Render(title) + " " + lineStyle.Render(strings.Repeat(char, remainingWidth))
32 }
33 return title
34}
35
36type StatusOpts struct {
37 Icon string
38 IconColor color.Color
39 Title string
40 TitleColor color.Color
41 Description string
42 DescriptionColor color.Color
43}
44
45func Status(ops StatusOpts, width int) string {
46 t := styles.CurrentTheme()
47 icon := "●"
48 iconColor := t.Success
49 if ops.Icon != "" {
50 icon = ops.Icon
51 }
52 if ops.IconColor != nil {
53 iconColor = ops.IconColor
54 }
55 title := ops.Title
56 titleColor := t.FgMuted
57 if ops.TitleColor != nil {
58 titleColor = ops.TitleColor
59 }
60 description := ops.Description
61 descriptionColor := t.FgSubtle
62 if ops.DescriptionColor != nil {
63 descriptionColor = ops.DescriptionColor
64 }
65 icon = t.S().Base.Foreground(iconColor).Render(icon)
66 title = t.S().Base.Foreground(titleColor).Render(title)
67 if description != "" {
68 description = ansi.Truncate(description, width-lipgloss.Width(icon)-lipgloss.Width(title)-2, "…")
69 }
70 description = t.S().Base.Foreground(descriptionColor).Render(description)
71 return strings.Join([]string{
72 icon,
73 title,
74 description,
75 }, " ")
76}