Files
Transmute/cli/internal/theme/theme.go
T
noah 04a1f33cb1 feat: add CLI with TUI, self-update, install script, and terminal section on landing page
- Full-screen Bubble Tea TUI with cream background fill using PadLine/FillBlankLines
- Self-update command (--update) pulling from GitHub releases
- install.sh for curl one-liner installation
- Terminal Lovers section on web landing page with install command and CLI features
- All 7 format categories, glob/directory batch support, auto-download ffmpeg
2026-03-09 22:53:10 +01:00

181 lines
3.9 KiB
Go

package theme
import (
"image/color"
"strings"
"charm.land/lipgloss/v2"
)
// ─── Pastel palette (matching the web app) ───────────────────
var (
Pink = lipgloss.Color("#f472b6")
Purple = lipgloss.Color("#a78bfa")
Blue = lipgloss.Color("#60a5fa")
Mint = lipgloss.Color("#34d399")
Orange = lipgloss.Color("#fb923c")
Teal = lipgloss.Color("#2dd4bf")
Cream = lipgloss.Color("#fdf6ef")
Warm = lipgloss.Color("#faf0e6")
Peach = lipgloss.Color("#fce8d5")
Dark = lipgloss.Color("#2d1f14")
Mid = lipgloss.Color("#8b7355")
Light = lipgloss.Color("#bfa98a")
Red = lipgloss.Color("#f43f5e")
DimBg = lipgloss.Color("#f6f6f6")
BorderCl = lipgloss.Color("#e8e0d4")
// Full-screen background
ScreenBg = lipgloss.Color("#fdf6ef") // Cream — matches the web app
)
// ─── Category colors ─────────────────────────────────────────
func CategoryColor(cat string) color.Color {
switch cat {
case "image":
return Pink
case "document":
return Blue
case "audio":
return Purple
case "video":
return Orange
case "data":
return Mint
case "font":
return Teal
case "spreadsheet":
return Mint
default:
return Light
}
}
// ─── Reusable styles ─────────────────────────────────────────
var (
// Title bar
TitleBar = lipgloss.NewStyle().
Bold(true).
Foreground(Dark).
Background(ScreenBg).
Padding(0, 2)
// Header / breadcrumb
Breadcrumb = lipgloss.NewStyle().
Foreground(Mid).
Bold(false)
BreadcrumbActive = lipgloss.NewStyle().
Foreground(Dark).
Bold(true)
// File row
FileName = lipgloss.NewStyle().
Foreground(Dark).
Bold(true)
FileSize = lipgloss.NewStyle().
Foreground(Light)
ExtBadge = func(c color.Color) lipgloss.Style {
return lipgloss.NewStyle().
Foreground(c).
Bold(true)
}
// Status indicators
StatusIdle = lipgloss.NewStyle().
Foreground(Light).
Italic(true)
StatusConverting = lipgloss.NewStyle().
Foreground(Pink).
Bold(true)
StatusDone = lipgloss.NewStyle().
Foreground(Mint).
Bold(true)
StatusError = lipgloss.NewStyle().
Foreground(Red).
Bold(true)
// Buttons / actions
ButtonPrimary = lipgloss.NewStyle().
Foreground(lipgloss.Color("#ffffff")).
Background(Pink).
Bold(true).
Padding(0, 2)
ButtonSecondary = lipgloss.NewStyle().
Foreground(lipgloss.Color("#ffffff")).
Background(Mint).
Bold(true).
Padding(0, 2)
// Progress bar
ProgressFilled = lipgloss.NewStyle().
Foreground(Pink)
ProgressEmpty = lipgloss.NewStyle().
Foreground(BorderCl)
// Help / footer
Help = lipgloss.NewStyle().
Foreground(Light).
Italic(true)
// Cursor / selection
Selected = lipgloss.NewStyle().
Bold(true).
Foreground(Pink)
Unselected = lipgloss.NewStyle().
Foreground(Dark)
// Divider
Divider = lipgloss.NewStyle().
Foreground(BorderCl)
// Logo / branding
Logo = lipgloss.NewStyle().
Foreground(Pink).
Bold(true)
)
// PadLine pads a single rendered line to the given width with the screen
// background color. This ensures every line carries the background color
// all the way to the right edge of the terminal.
func PadLine(line string, width int) string {
w := lipgloss.Width(line)
if w >= width {
return line
}
pad := lipgloss.NewStyle().
Background(ScreenBg).
Render(strings.Repeat(" ", width-w))
return line + pad
}
// FillBlankLines returns n blank lines fully painted with the screen
// background color at the given width.
func FillBlankLines(n, width int) string {
if n <= 0 {
return ""
}
blankLine := lipgloss.NewStyle().
Background(ScreenBg).
Render(strings.Repeat(" ", width))
lines := make([]string, n)
for i := range lines {
lines[i] = blankLine
}
return strings.Join(lines, "\n")
}