diff options
| author | Kujtim Hoxha <[email protected]> | 2025-03-21 18:20:28 +0100 |
|---|---|---|
| committer | Kujtim Hoxha <[email protected]> | 2025-03-21 18:20:28 +0100 |
| commit | 4b0ea68d7af9a6031a7ffda7ad66e0cb83315750 (patch) | |
| tree | 8220c1bf6f107ea76dd78c7f57b77000c0c98a22 /internal/tui/layout/border.go | |
| download | opencode-4b0ea68d7af9a6031a7ffda7ad66e0cb83315750.tar.gz opencode-4b0ea68d7af9a6031a7ffda7ad66e0cb83315750.zip | |
initial
Diffstat (limited to 'internal/tui/layout/border.go')
| -rw-r--r-- | internal/tui/layout/border.go | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/internal/tui/layout/border.go b/internal/tui/layout/border.go new file mode 100644 index 000000000..d1b334b32 --- /dev/null +++ b/internal/tui/layout/border.go @@ -0,0 +1,99 @@ +package layout + +import ( + "fmt" + "strings" + + "github.com/charmbracelet/lipgloss" + "github.com/kujtimiihoxha/termai/internal/tui/styles" +) + +type BorderPosition int + +const ( + TopLeftBorder BorderPosition = iota + TopMiddleBorder + TopRightBorder + BottomLeftBorder + BottomMiddleBorder + BottomRightBorder +) + +var ( + ActiveBorder = styles.Blue + InactivePreviewBorder = styles.Grey +) + +func Borderize(content string, active bool, embeddedText map[BorderPosition]string) string { + if embeddedText == nil { + embeddedText = make(map[BorderPosition]string) + } + var ( + thickness = map[bool]lipgloss.Border{ + true: lipgloss.Border(lipgloss.ThickBorder()), + false: lipgloss.Border(lipgloss.NormalBorder()), + } + color = map[bool]lipgloss.TerminalColor{ + true: ActiveBorder, + false: InactivePreviewBorder, + } + border = thickness[active] + style = lipgloss.NewStyle().Foreground(color[active]) + width = lipgloss.Width(content) + ) + + encloseInSquareBrackets := func(text string) string { + if text != "" { + return fmt.Sprintf("%s%s%s", + style.Render(border.TopRight), + text, + style.Render(border.TopLeft), + ) + } + return text + } + buildHorizontalBorder := func(leftText, middleText, rightText, leftCorner, inbetween, rightCorner string) string { + leftText = encloseInSquareBrackets(leftText) + middleText = encloseInSquareBrackets(middleText) + rightText = encloseInSquareBrackets(rightText) + // Calculate length of border between embedded texts + remaining := max(0, width-lipgloss.Width(leftText)-lipgloss.Width(middleText)-lipgloss.Width(rightText)) + leftBorderLen := max(0, (width/2)-lipgloss.Width(leftText)-(lipgloss.Width(middleText)/2)) + rightBorderLen := max(0, remaining-leftBorderLen) + // Then construct border string + s := leftText + + style.Render(strings.Repeat(inbetween, leftBorderLen)) + + middleText + + style.Render(strings.Repeat(inbetween, rightBorderLen)) + + rightText + // Make it fit in the space available between the two corners. + s = lipgloss.NewStyle(). + Inline(true). + MaxWidth(width). + Render(s) + // Add the corners + return style.Render(leftCorner) + s + style.Render(rightCorner) + } + // Stack top border, content and horizontal borders, and bottom border. + return strings.Join([]string{ + buildHorizontalBorder( + embeddedText[TopLeftBorder], + embeddedText[TopMiddleBorder], + embeddedText[TopRightBorder], + border.TopLeft, + border.Top, + border.TopRight, + ), + lipgloss.NewStyle(). + BorderForeground(color[active]). + Border(border, false, true, false, true).Render(content), + buildHorizontalBorder( + embeddedText[BottomLeftBorder], + embeddedText[BottomMiddleBorder], + embeddedText[BottomRightBorder], + border.BottomLeft, + border.Bottom, + border.BottomRight, + ), + }, "\n") +} |
