Add offline-first task-master TUI with tickets, board lists, and undo.

Charm-based CLI with JSON persistence, status/list filters, external editor editing, command-history undo/redo, and glamour markdown without AutoStyle OSC hangs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Skruecken
2026-10-19 10:21:48 +02:00
co-authored by Cursor
parent 4a3d0d777b
commit 24c1e146ec
37 changed files with 3259 additions and 0 deletions
+120
View File
@@ -0,0 +1,120 @@
package ui
import "github.com/charmbracelet/lipgloss"
// Styles holds Lipgloss styles for the TUI.
type Styles struct {
Header lipgloss.Style
HeaderBrand lipgloss.Style
HeaderMeta lipgloss.Style
HelpKey lipgloss.Style
HelpDesc lipgloss.Style
HelpSep lipgloss.Style
Version lipgloss.Style
StatusTodo lipgloss.Style
StatusWIP lipgloss.Style
StatusDone lipgloss.Style
StatusMsg lipgloss.Style
ErrorMsg lipgloss.Style
Selected lipgloss.Style
Normal lipgloss.Style
InputPrompt lipgloss.Style
FilterHint lipgloss.Style
Card lipgloss.Style
CardSelected lipgloss.Style
Headline lipgloss.Style
StatusMenuBox lipgloss.Style
StatusMenuTitle lipgloss.Style
StatusMenuSelected lipgloss.Style
StatusMenuNormal lipgloss.Style
}
// DefaultStyles returns the neutral terminal theme.
func DefaultStyles() Styles {
accent := lipgloss.Color("39")
faint := lipgloss.Color("245")
green := lipgloss.Color("42")
yellow := lipgloss.Color("214")
muted := lipgloss.Color("240")
border := lipgloss.Color("238")
borderSel := lipgloss.Color("39")
return Styles{
Header: lipgloss.NewStyle().
Bold(true).
Padding(0, 1),
HeaderBrand: lipgloss.NewStyle().
Bold(true).
Foreground(accent),
HeaderMeta: lipgloss.NewStyle().
Foreground(faint),
HelpKey: lipgloss.NewStyle().
Bold(true).
Foreground(accent),
HelpDesc: lipgloss.NewStyle().
Foreground(faint),
HelpSep: lipgloss.NewStyle().
Foreground(muted).
SetString(" "),
Version: lipgloss.NewStyle().
Faint(true).
Foreground(muted),
StatusTodo: lipgloss.NewStyle().
Foreground(faint).
Background(lipgloss.Color("236")),
StatusWIP: lipgloss.NewStyle().
Foreground(lipgloss.Color("0")).
Background(yellow).
Bold(true),
StatusDone: lipgloss.NewStyle().
Foreground(lipgloss.Color("0")).
Background(green),
StatusMsg: lipgloss.NewStyle().
Foreground(faint),
ErrorMsg: lipgloss.NewStyle().
Foreground(lipgloss.Color("196")),
Selected: lipgloss.NewStyle().
Foreground(lipgloss.Color("230")).
Background(accent).
Bold(true),
Normal: lipgloss.NewStyle(),
InputPrompt: lipgloss.NewStyle().
Foreground(accent).
Bold(true),
FilterHint: lipgloss.NewStyle().
Foreground(yellow),
// Left accent only — full box borders stacked a blank line between tickets.
Card: lipgloss.NewStyle().
BorderStyle(lipgloss.NormalBorder()).
BorderLeft(true).
BorderTop(false).
BorderRight(false).
BorderBottom(false).
BorderForeground(border).
PaddingLeft(1),
CardSelected: lipgloss.NewStyle().
BorderStyle(lipgloss.ThickBorder()).
BorderLeft(true).
BorderTop(false).
BorderRight(false).
BorderBottom(false).
BorderForeground(borderSel).
PaddingLeft(1),
Headline: lipgloss.NewStyle().
Bold(true),
StatusMenuBox: lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(accent).
Padding(1, 2),
StatusMenuTitle: lipgloss.NewStyle().
Bold(true).
Foreground(accent).
MarginBottom(1),
StatusMenuSelected: lipgloss.NewStyle().
Foreground(lipgloss.Color("230")).
Background(accent).
Bold(true),
StatusMenuNormal: lipgloss.NewStyle().
Foreground(faint),
}
}