detached 539e660

fix(ui): improve logo branding and tagline centering

- render ARCHUP logo in full blue (removed two-tone split)
- fix tagline centering using lipgloss.Width instead of len
- lipgloss.Width properly handles ANSI color codes for accurate centering
- removed unused splitPos constant
commit
539e6603fb4e673a44a107bd315a69da6fdfe5bb
author
bnema · · 2025-10-26 11:37 UTC
parent
62374aa
signature
unsigned
2 files · +7 -21
M internal/ui/logo.go +3 -19
@@ -10,15 +10,12 @@ import (
1010
1111 const (
1212 // Logo ASCII art (from logo.txt)
13- // Split at column 34 for two-tone color scheme (cyan/white)
1413 logoASCII = ` ░█████╗░██████╗░░█████╗░██╗░░██╗██╗░░░██╗██████╗░
1514 ██╔══██╗██╔══██╗██╔══██╗██║░░██║██║░░░██║██╔══██╗
1615 ███████║██████╔╝██║░░╚═╝███████║██║░░░██║██████╔╝
1716 ██╔══██║██╔══██╗██║░░██╗██╔══██║██║░░░██║██╔═══╝░
1817 ██║░░██║██║░░██║╚█████╔╝██║░░██║╚██████╔╝██║░░░░░
1918 ╚═╝░░╚═╝╚═╝░░╚═╝░╚════╝░╚═╝░░╚═╝░╚═════╝░╚═╝░░░░░`
20-
21- splitPos = 34 // Column where color split occurs
2219 )
2320
2421 // Logo represents the ArchUp logo display
@@ -50,7 +47,7 @@ func NewLogo(version string) *Logo {
5047 }
5148 }
5249
53-// Render renders the logo with two-tone coloring (cyan/white split)
50+// Render renders the logo in full blue
5451 func (l *Logo) Render() string {
5552 lines := strings.Split(logoASCII, "\n")
5653 var rendered strings.Builder
@@ -61,21 +58,8 @@ func (l *Logo) Render() string {
6158 continue
6259 }
6360
64- // Split line at splitPos for two-tone effect
65- var left, right string
66- if len(line) > splitPos {
67- left = line[:splitPos]
68- right = line[splitPos:]
69- } else {
70- left = line
71- right = ""
72- }
73-
74- // Render with colors
75- rendered.WriteString(styles.LogoCyanStyle.Render(left))
76- if right != "" {
77- rendered.WriteString(styles.LogoWhiteStyle.Render(right))
78- }
61+ // Render entire logo in blue
62+ rendered.WriteString(styles.LogoCyanStyle.Render(line))
7963 rendered.WriteString("\n")
8064 }
8165
@@ -10,15 +10,12 @@ import (
10 10
11 const (11 const (
12 // Logo ASCII art (from logo.txt)12 // Logo ASCII art (from logo.txt)
13- // Split at column 34 for two-tone color scheme (cyan/white)
14 logoASCII = ` ░█████╗░██████╗░░█████╗░██╗░░██╗██╗░░░██╗██████╗░13 logoASCII = ` ░█████╗░██████╗░░█████╗░██╗░░██╗██╗░░░██╗██████╗░
15 ██╔══██╗██╔══██╗██╔══██╗██║░░██║██║░░░██║██╔══██╗14 ██╔══██╗██╔══██╗██╔══██╗██║░░██║██║░░░██║██╔══██╗
16 ███████║██████╔╝██║░░╚═╝███████║██║░░░██║██████╔╝15 ███████║██████╔╝██║░░╚═╝███████║██║░░░██║██████╔╝
17 ██╔══██║██╔══██╗██║░░██╗██╔══██║██║░░░██║██╔═══╝░16 ██╔══██║██╔══██╗██║░░██╗██╔══██║██║░░░██║██╔═══╝░
18 ██║░░██║██║░░██║╚█████╔╝██║░░██║╚██████╔╝██║░░░░░17 ██║░░██║██║░░██║╚█████╔╝██║░░██║╚██████╔╝██║░░░░░
19 ╚═╝░░╚═╝╚═╝░░╚═╝░╚════╝░╚═╝░░╚═╝░╚═════╝░╚═╝░░░░░`18 ╚═╝░░╚═╝╚═╝░░╚═╝░╚════╝░╚═╝░░╚═╝░╚═════╝░╚═╝░░░░░`
20-
21- splitPos = 34 // Column where color split occurs
22 )19 )
23 20
24 // Logo represents the ArchUp logo display21 // Logo represents the ArchUp logo display
@@ -50,7 +47,7 @@ func NewLogo(version string) *Logo {
50 }47 }
51 }48 }
52 49
53-// Render renders the logo with two-tone coloring (cyan/white split)50+// Render renders the logo in full blue
54 func (l *Logo) Render() string {51 func (l *Logo) Render() string {
55 lines := strings.Split(logoASCII, "\n")52 lines := strings.Split(logoASCII, "\n")
56 var rendered strings.Builder53 var rendered strings.Builder
@@ -61,21 +58,8 @@ func (l *Logo) Render() string {
61 continue58 continue
62 }59 }
63 60
64- // Split line at splitPos for two-tone effect61+ // Render entire logo in blue
65- var left, right string62+ rendered.WriteString(styles.LogoCyanStyle.Render(line))
66- if len(line) > splitPos {
67- left = line[:splitPos]
68- right = line[splitPos:]
69- } else {
70- left = line
71- right = ""
72- }
73-
74- // Render with colors
75- rendered.WriteString(styles.LogoCyanStyle.Render(left))
76- if right != "" {
77- rendered.WriteString(styles.LogoWhiteStyle.Render(right))
78- }
79 rendered.WriteString("\n")63 rendered.WriteString("\n")
80 }64 }
81 65
M internal/ui/model.go +4 -2
@@ -2,9 +2,11 @@ package ui
22
33 import (
44 "fmt"
5+ "strings"
56
67 tea "github.com/charmbracelet/bubbletea"
78 "github.com/charmbracelet/huh"
9+ "github.com/charmbracelet/lipgloss"
810 "github.com/bnema/archup/internal/config"
911 "github.com/bnema/archup/internal/phases"
1012 "github.com/bnema/archup/internal/ui/components"
@@ -245,11 +247,11 @@ type phaseCompleteMsg struct {
245247
246248 // centerText centers text within a given width
247249 func centerText(text string, width int) string {
248- textLen := len(text)
250+ textLen := lipgloss.Width(text)
249251 switch {
250252 case textLen >= width:
251253 return text
252254 }
253255 padding := (width - textLen) / 2
254- return fmt.Sprintf("%*s", padding+textLen, text)
256+ return strings.Repeat(" ", padding) + text
255257 }
@@ -2,9 +2,11 @@ package ui
2 2
3 import (3 import (
4 "fmt"4 "fmt"
5+ "strings"
5 6
6 tea "github.com/charmbracelet/bubbletea"7 tea "github.com/charmbracelet/bubbletea"
7 "github.com/charmbracelet/huh"8 "github.com/charmbracelet/huh"
9+ "github.com/charmbracelet/lipgloss"
8 "github.com/bnema/archup/internal/config"10 "github.com/bnema/archup/internal/config"
9 "github.com/bnema/archup/internal/phases"11 "github.com/bnema/archup/internal/phases"
10 "github.com/bnema/archup/internal/ui/components"12 "github.com/bnema/archup/internal/ui/components"
@@ -245,11 +247,11 @@ type phaseCompleteMsg struct {
245 247
246 // centerText centers text within a given width248 // centerText centers text within a given width
247 func centerText(text string, width int) string {249 func centerText(text string, width int) string {
248- textLen := len(text)250+ textLen := lipgloss.Width(text)
249 switch {251 switch {
250 case textLen >= width:252 case textLen >= width:
251 return text253 return text
252 }254 }
253 padding := (width - textLen) / 2255 padding := (width - textLen) / 2
254- return fmt.Sprintf("%*s", padding+textLen, text)256+ return strings.Repeat(" ", padding) + text
255 }257 }

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 0

    ↑↓ moveenter openesc close