Merge pull request #2 from oug-t/feat/vim-motions
feat: vim motions support
This commit is contained in:
commit
d8dd109c3f
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/charmbracelet/bubbles/list"
|
"github.com/charmbracelet/bubbles/list"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TreeItem represents a file or folder in the UI list.
|
||||||
type TreeItem struct {
|
type TreeItem struct {
|
||||||
Path string
|
Path string
|
||||||
FullPath string
|
FullPath string
|
||||||
|
|
@ -24,9 +25,16 @@ func (i TreeItem) Title() string {
|
||||||
return fmt.Sprintf("%s%s %s", indent, icon, i.Path)
|
return fmt.Sprintf("%s%s %s", indent, icon, i.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build converts a list of file paths into a compacted, sorted tree list.
|
||||||
func Build(paths []string) []list.Item {
|
func Build(paths []string) []list.Item {
|
||||||
root := &node{children: make(map[string]*node)}
|
// FIX 1: Initialize root as a directory so logic works,
|
||||||
|
// but we won't compact the root itself.
|
||||||
|
root := &node{
|
||||||
|
children: make(map[string]*node),
|
||||||
|
isDir: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Build the raw tree structure
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
parts := strings.Split(path, "/")
|
parts := strings.Split(path, "/")
|
||||||
current := root
|
current := root
|
||||||
|
|
@ -45,11 +53,20 @@ func Build(paths []string) []list.Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIX 2: Do NOT compact the root node itself (which would hide top-level folders).
|
||||||
|
// Instead, compact each top-level child individually.
|
||||||
|
for _, child := range root.children {
|
||||||
|
compact(child)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Flatten to list items
|
||||||
var items []list.Item
|
var items []list.Item
|
||||||
flatten(root, 0, &items)
|
flatten(root, 0, &items)
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- Helpers --
|
||||||
|
|
||||||
type node struct {
|
type node struct {
|
||||||
name string
|
name string
|
||||||
fullPath string
|
fullPath string
|
||||||
|
|
@ -57,6 +74,35 @@ type node struct {
|
||||||
isDir bool
|
isDir bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compact recursively merges directories that contain only a single directory child.
|
||||||
|
func compact(n *node) {
|
||||||
|
if !n.isDir {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compact children first (bottom-up traversal)
|
||||||
|
for _, child := range n.children {
|
||||||
|
compact(child)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logic: If I am a directory, and I have exactly 1 child, and that child is also a directory...
|
||||||
|
if len(n.children) == 1 {
|
||||||
|
var child *node
|
||||||
|
for _, c := range n.children {
|
||||||
|
child = c
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if child.isDir {
|
||||||
|
// Merge child into parent
|
||||||
|
// e.g. "internal" + "ui" becomes "internal/ui"
|
||||||
|
n.name = filepath.Join(n.name, child.name)
|
||||||
|
n.fullPath = child.fullPath
|
||||||
|
n.children = child.children // Inherit grandchildren
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func flatten(n *node, depth int, items *[]list.Item) {
|
func flatten(n *node, depth int, items *[]list.Item) {
|
||||||
keys := make([]string, 0, len(n.children))
|
keys := make([]string, 0, len(n.children))
|
||||||
for k := range n.children {
|
for k := range n.children {
|
||||||
|
|
@ -65,6 +111,7 @@ func flatten(n *node, depth int, items *[]list.Item) {
|
||||||
|
|
||||||
sort.Slice(keys, func(i, j int) bool {
|
sort.Slice(keys, func(i, j int) bool {
|
||||||
a, b := n.children[keys[i]], n.children[keys[j]]
|
a, b := n.children[keys[i]], n.children[keys[j]]
|
||||||
|
// Folders first
|
||||||
if a.isDir && !b.isDir {
|
if a.isDir && !b.isDir {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -82,6 +129,7 @@ func flatten(n *node, depth int, items *[]list.Item) {
|
||||||
IsDir: child.isDir,
|
IsDir: child.isDir,
|
||||||
Depth: depth,
|
Depth: depth,
|
||||||
})
|
})
|
||||||
|
|
||||||
if child.isDir {
|
if child.isDir {
|
||||||
flatten(child, depth+1, items)
|
flatten(child, depth+1, items)
|
||||||
}
|
}
|
||||||
|
|
@ -90,29 +138,31 @@ func flatten(n *node, depth int, items *[]list.Item) {
|
||||||
|
|
||||||
func getIcon(name string, isDir bool) string {
|
func getIcon(name string, isDir bool) string {
|
||||||
if isDir {
|
if isDir {
|
||||||
return ""
|
return " "
|
||||||
}
|
}
|
||||||
ext := filepath.Ext(name)
|
ext := filepath.Ext(name)
|
||||||
switch strings.ToLower(ext) {
|
switch strings.ToLower(ext) {
|
||||||
case ".go":
|
case ".go":
|
||||||
return ""
|
return " "
|
||||||
case ".js", ".ts":
|
case ".js", ".ts", ".tsx":
|
||||||
return ""
|
return " "
|
||||||
|
case ".svelte":
|
||||||
|
return " "
|
||||||
case ".md":
|
case ".md":
|
||||||
return ""
|
return " "
|
||||||
case ".json":
|
case ".json":
|
||||||
return ""
|
return " "
|
||||||
case ".yml", ".yaml":
|
case ".yml", ".yaml":
|
||||||
return ""
|
return " "
|
||||||
case ".html":
|
case ".html":
|
||||||
return ""
|
return " "
|
||||||
case ".css":
|
case ".css":
|
||||||
return ""
|
return " "
|
||||||
case ".git":
|
case ".git":
|
||||||
return ""
|
return " "
|
||||||
case ".dockerfile":
|
case ".dockerfile":
|
||||||
return ""
|
return " "
|
||||||
default:
|
default:
|
||||||
return ""
|
return " "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ package ui
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/charmbracelet/bubbles/list"
|
"github.com/charmbracelet/bubbles/list"
|
||||||
|
|
@ -37,6 +39,9 @@ type Model struct {
|
||||||
diffLines []string
|
diffLines []string
|
||||||
diffCursor int
|
diffCursor int
|
||||||
|
|
||||||
|
// Input State for Vim Motions
|
||||||
|
inputBuffer string
|
||||||
|
|
||||||
// UI State
|
// UI State
|
||||||
focus Focus
|
focus Focus
|
||||||
showHelp bool
|
showHelp bool
|
||||||
|
|
@ -62,6 +67,7 @@ func NewModel() Model {
|
||||||
currentBranch: git.GetCurrentBranch(),
|
currentBranch: git.GetCurrentBranch(),
|
||||||
repoName: git.GetRepoName(),
|
repoName: git.GetRepoName(),
|
||||||
showHelp: false,
|
showHelp: false,
|
||||||
|
inputBuffer: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(items) > 0 {
|
if len(items) > 0 {
|
||||||
|
|
@ -79,10 +85,25 @@ func (m Model) Init() tea.Cmd {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Model) getRepeatCount() int {
|
||||||
|
if m.inputBuffer == "" {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
count, err := strconv.Atoi(m.inputBuffer)
|
||||||
|
if err != nil {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
m.inputBuffer = ""
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
var cmd tea.Cmd
|
var cmd tea.Cmd
|
||||||
var cmds []tea.Cmd
|
var cmds []tea.Cmd
|
||||||
|
|
||||||
|
// Flag to track if we manually handled navigation
|
||||||
|
keyHandled := false
|
||||||
|
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case tea.WindowSizeMsg:
|
case tea.WindowSizeMsg:
|
||||||
m.width = msg.Width
|
m.width = msg.Width
|
||||||
|
|
@ -90,19 +111,21 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
m.updateSizes()
|
m.updateSizes()
|
||||||
|
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
// Toggle Help
|
if len(msg.String()) == 1 && strings.ContainsAny(msg.String(), "0123456789") {
|
||||||
|
m.inputBuffer += msg.String()
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
if msg.String() == "?" {
|
if msg.String() == "?" {
|
||||||
m.showHelp = !m.showHelp
|
m.showHelp = !m.showHelp
|
||||||
m.updateSizes()
|
m.updateSizes()
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit
|
|
||||||
if msg.String() == "q" || msg.String() == "ctrl+c" {
|
if msg.String() == "q" || msg.String() == "ctrl+c" {
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navigation
|
|
||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
case "tab":
|
case "tab":
|
||||||
if m.focus == FocusTree {
|
if m.focus == FocusTree {
|
||||||
|
|
@ -110,14 +133,16 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
} else {
|
} else {
|
||||||
m.focus = FocusTree
|
m.focus = FocusTree
|
||||||
}
|
}
|
||||||
|
m.inputBuffer = ""
|
||||||
|
|
||||||
case "l", "]", "ctrl+l", "right":
|
case "l", "]", "ctrl+l", "right":
|
||||||
m.focus = FocusDiff
|
m.focus = FocusDiff
|
||||||
|
m.inputBuffer = ""
|
||||||
|
|
||||||
case "h", "[", "ctrl+h", "left":
|
case "h", "[", "ctrl+h", "left":
|
||||||
m.focus = FocusTree
|
m.focus = FocusTree
|
||||||
|
m.inputBuffer = ""
|
||||||
|
|
||||||
// Editing
|
|
||||||
case "e", "enter":
|
case "e", "enter":
|
||||||
if m.selectedPath != "" {
|
if m.selectedPath != "" {
|
||||||
line := 0
|
line := 0
|
||||||
|
|
@ -126,35 +151,56 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
} else {
|
} else {
|
||||||
line = git.CalculateFileLine(m.diffContent, 0)
|
line = git.CalculateFileLine(m.diffContent, 0)
|
||||||
}
|
}
|
||||||
|
m.inputBuffer = ""
|
||||||
return m, git.OpenEditorCmd(m.selectedPath, line)
|
return m, git.OpenEditorCmd(m.selectedPath, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diff Cursor
|
// Vim Motions
|
||||||
case "j", "down":
|
case "j", "down":
|
||||||
if m.focus == FocusDiff {
|
keyHandled = true // Mark as handled so we don't pass to list.Update()
|
||||||
if m.diffCursor < len(m.diffLines)-1 {
|
count := m.getRepeatCount()
|
||||||
m.diffCursor++
|
for i := 0; i < count; i++ {
|
||||||
if m.diffCursor >= m.diffViewport.YOffset+m.diffViewport.Height {
|
if m.focus == FocusDiff {
|
||||||
m.diffViewport.LineDown(1)
|
if m.diffCursor < len(m.diffLines)-1 {
|
||||||
|
m.diffCursor++
|
||||||
|
if m.diffCursor >= m.diffViewport.YOffset+m.diffViewport.Height {
|
||||||
|
m.diffViewport.LineDown(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
m.fileTree.CursorDown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m.inputBuffer = ""
|
||||||
|
|
||||||
case "k", "up":
|
case "k", "up":
|
||||||
if m.focus == FocusDiff {
|
keyHandled = true // Mark as handled
|
||||||
if m.diffCursor > 0 {
|
count := m.getRepeatCount()
|
||||||
m.diffCursor--
|
for i := 0; i < count; i++ {
|
||||||
if m.diffCursor < m.diffViewport.YOffset {
|
if m.focus == FocusDiff {
|
||||||
m.diffViewport.LineUp(1)
|
if m.diffCursor > 0 {
|
||||||
|
m.diffCursor--
|
||||||
|
if m.diffCursor < m.diffViewport.YOffset {
|
||||||
|
m.diffViewport.LineUp(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
m.fileTree.CursorUp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m.inputBuffer = ""
|
||||||
|
|
||||||
|
default:
|
||||||
|
m.inputBuffer = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update Components
|
// Update Components
|
||||||
if m.focus == FocusTree {
|
if m.focus == FocusTree {
|
||||||
m.fileTree, cmd = m.fileTree.Update(msg)
|
if !keyHandled {
|
||||||
cmds = append(cmds, cmd)
|
m.fileTree, cmd = m.fileTree.Update(msg)
|
||||||
|
cmds = append(cmds, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
if item, ok := m.fileTree.SelectedItem().(tree.TreeItem); ok && !item.IsDir {
|
if item, ok := m.fileTree.SelectedItem().(tree.TreeItem); ok && !item.IsDir {
|
||||||
if item.FullPath != m.selectedPath {
|
if item.FullPath != m.selectedPath {
|
||||||
|
|
@ -226,12 +272,19 @@ func (m Model) View() string {
|
||||||
|
|
||||||
for i := start; i < end; i++ {
|
for i := start; i < end; i++ {
|
||||||
line := m.diffLines[i]
|
line := m.diffLines[i]
|
||||||
|
|
||||||
|
// Relative Numbers
|
||||||
|
distance := int(math.Abs(float64(i - m.diffCursor)))
|
||||||
|
relNum := fmt.Sprintf("%d", distance)
|
||||||
|
lineNumStr := LineNumberStyle.Render(relNum)
|
||||||
|
|
||||||
if m.focus == FocusDiff && i == m.diffCursor {
|
if m.focus == FocusDiff && i == m.diffCursor {
|
||||||
line = SelectedItemStyle.Render(line)
|
line = SelectedItemStyle.Render(line)
|
||||||
} else {
|
} else {
|
||||||
line = " " + line
|
line = " " + line
|
||||||
}
|
}
|
||||||
renderedDiff.WriteString(line + "\n")
|
|
||||||
|
renderedDiff.WriteString(lineNumStr + line + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
diffView := DiffStyle.Copy().
|
diffView := DiffStyle.Copy().
|
||||||
|
|
@ -241,10 +294,14 @@ func (m Model) View() string {
|
||||||
|
|
||||||
mainPanes := lipgloss.JoinHorizontal(lipgloss.Top, treeView, diffView)
|
mainPanes := lipgloss.JoinHorizontal(lipgloss.Top, treeView, diffView)
|
||||||
|
|
||||||
// Status Bar
|
|
||||||
repoSection := StatusKeyStyle.Render(" " + m.repoName)
|
repoSection := StatusKeyStyle.Render(" " + m.repoName)
|
||||||
divider := StatusDividerStyle.Render("│")
|
divider := StatusDividerStyle.Render("│")
|
||||||
branchSection := StatusBarStyle.Render(fmt.Sprintf(" %s ↔ %s", m.currentBranch, TargetBranch))
|
|
||||||
|
statusText := fmt.Sprintf(" %s ↔ %s", m.currentBranch, TargetBranch)
|
||||||
|
if m.inputBuffer != "" {
|
||||||
|
statusText += fmt.Sprintf(" [Cmd: %s]", m.inputBuffer)
|
||||||
|
}
|
||||||
|
branchSection := StatusBarStyle.Render(statusText)
|
||||||
|
|
||||||
leftStatus := lipgloss.JoinHorizontal(lipgloss.Center, repoSection, divider, branchSection)
|
leftStatus := lipgloss.JoinHorizontal(lipgloss.Center, repoSection, divider, branchSection)
|
||||||
rightStatus := StatusBarStyle.Render("? Help")
|
rightStatus := StatusBarStyle.Render("? Help")
|
||||||
|
|
@ -256,7 +313,6 @@ func (m Model) View() string {
|
||||||
lipgloss.PlaceHorizontal(m.width-lipgloss.Width(leftStatus)-lipgloss.Width(rightStatus), lipgloss.Right, rightStatus),
|
lipgloss.PlaceHorizontal(m.width-lipgloss.Width(leftStatus)-lipgloss.Width(rightStatus), lipgloss.Right, rightStatus),
|
||||||
))
|
))
|
||||||
|
|
||||||
// Help Drawer
|
|
||||||
var finalView string
|
var finalView string
|
||||||
if m.showHelp {
|
if m.showHelp {
|
||||||
col1 := lipgloss.JoinVertical(lipgloss.Left,
|
col1 := lipgloss.JoinVertical(lipgloss.Left,
|
||||||
|
|
@ -269,10 +325,10 @@ func (m Model) View() string {
|
||||||
)
|
)
|
||||||
col3 := lipgloss.JoinVertical(lipgloss.Left,
|
col3 := lipgloss.JoinVertical(lipgloss.Left,
|
||||||
HelpTextStyle.Render("Tab Switch Panel"),
|
HelpTextStyle.Render("Tab Switch Panel"),
|
||||||
HelpTextStyle.Render("Ent/e Edit File"),
|
HelpTextStyle.Render("Num Motion Count"),
|
||||||
)
|
)
|
||||||
col4 := lipgloss.JoinVertical(lipgloss.Left,
|
col4 := lipgloss.JoinVertical(lipgloss.Left,
|
||||||
HelpTextStyle.Render("q Quit"),
|
HelpTextStyle.Render("e Edit File"),
|
||||||
HelpTextStyle.Render("? Close Help"),
|
HelpTextStyle.Render("? Close Help"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,15 @@ package ui
|
||||||
import "github.com/charmbracelet/lipgloss"
|
import "github.com/charmbracelet/lipgloss"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// -- THEME: Neutral & Clean --
|
|
||||||
ColorBorder = lipgloss.AdaptiveColor{Light: "#D9DCCF", Dark: "#383838"}
|
ColorBorder = lipgloss.AdaptiveColor{Light: "#D9DCCF", Dark: "#383838"}
|
||||||
ColorFocus = lipgloss.AdaptiveColor{Light: "#000000", Dark: "#E5E5E5"}
|
ColorFocus = lipgloss.AdaptiveColor{Light: "#000000", Dark: "#E5E5E5"}
|
||||||
ColorText = lipgloss.AdaptiveColor{Light: "#1F1F1F", Dark: "#F8F8F2"}
|
ColorText = lipgloss.AdaptiveColor{Light: "#1F1F1F", Dark: "#F8F8F2"}
|
||||||
ColorSubtle = lipgloss.AdaptiveColor{Light: "#A8A8A8", Dark: "#626262"}
|
ColorSubtle = lipgloss.AdaptiveColor{Light: "#A8A8A8", Dark: "#626262"}
|
||||||
ColorCursorBg = lipgloss.AdaptiveColor{Light: "#E5E5E5", Dark: "#3E3E3E"}
|
ColorCursorBg = lipgloss.AdaptiveColor{Light: "#E5E5E5", Dark: "#3E3E3E"}
|
||||||
|
|
||||||
// -- Status Bar Colors --
|
|
||||||
ColorBarBg = lipgloss.AdaptiveColor{Light: "#F2F2F2", Dark: "#1F1F1F"}
|
ColorBarBg = lipgloss.AdaptiveColor{Light: "#F2F2F2", Dark: "#1F1F1F"}
|
||||||
ColorBarFg = lipgloss.AdaptiveColor{Light: "#6E6E6E", Dark: "#9E9E9E"}
|
ColorBarFg = lipgloss.AdaptiveColor{Light: "#6E6E6E", Dark: "#9E9E9E"}
|
||||||
|
|
||||||
// -- PANE STYLES --
|
|
||||||
PaneStyle = lipgloss.NewStyle().
|
PaneStyle = lipgloss.NewStyle().
|
||||||
Border(lipgloss.NormalBorder(), false, true, false, false).
|
Border(lipgloss.NormalBorder(), false, true, false, false).
|
||||||
BorderForeground(ColorBorder)
|
BorderForeground(ColorBorder)
|
||||||
|
|
@ -32,32 +29,14 @@ var (
|
||||||
Bold(true).
|
Bold(true).
|
||||||
Width(1000)
|
Width(1000)
|
||||||
|
|
||||||
// -- STATUS BAR STYLES --
|
LineNumberStyle = lipgloss.NewStyle().
|
||||||
StatusBarStyle = lipgloss.NewStyle().
|
Foreground(lipgloss.Color("#707070")). // Solid gray, easy to read
|
||||||
Foreground(ColorBarFg).
|
PaddingRight(1).
|
||||||
Background(ColorBarBg).
|
Width(4)
|
||||||
Padding(0, 1)
|
|
||||||
|
|
||||||
StatusKeyStyle = lipgloss.NewStyle().
|
StatusBarStyle = lipgloss.NewStyle().Foreground(ColorBarFg).Background(ColorBarBg).Padding(0, 1)
|
||||||
Foreground(ColorText).
|
StatusKeyStyle = lipgloss.NewStyle().Foreground(ColorText).Background(ColorBarBg).Bold(true).Padding(0, 1)
|
||||||
Background(ColorBarBg).
|
StatusDividerStyle = lipgloss.NewStyle().Foreground(ColorSubtle).Background(ColorBarBg).Padding(0, 0)
|
||||||
Bold(true).
|
HelpTextStyle = lipgloss.NewStyle().Foreground(ColorSubtle).Padding(0, 1)
|
||||||
Padding(0, 1)
|
HelpDrawerStyle = lipgloss.NewStyle().Border(lipgloss.NormalBorder(), true, false, false, false).BorderForeground(ColorBorder).Padding(1, 2)
|
||||||
|
|
||||||
StatusDividerStyle = lipgloss.NewStyle().
|
|
||||||
Foreground(ColorSubtle).
|
|
||||||
Background(ColorBarBg).
|
|
||||||
Padding(0, 0)
|
|
||||||
|
|
||||||
// -- NEW HELP STYLES (Transparent & Subtle) --
|
|
||||||
// No background, subtle color, no bold
|
|
||||||
HelpTextStyle = lipgloss.NewStyle().
|
|
||||||
Foreground(ColorSubtle).
|
|
||||||
Padding(0, 1)
|
|
||||||
|
|
||||||
HelpDrawerStyle = lipgloss.NewStyle().
|
|
||||||
// No Background() definition means transparent
|
|
||||||
Border(lipgloss.NormalBorder(), true, false, false, false). // Top border only
|
|
||||||
BorderForeground(ColorBorder).
|
|
||||||
Padding(1, 2)
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user