55 "strings"
66
77 "github.com/charmbracelet/lipgloss"
8+
89 "github.com/venkatkrishna07/mkdev/internal/tui/styles"
910)
1011
@@ -19,31 +20,73 @@ func useGlyphs() bool {
1920 return os .Getenv ("NO_NERD_FONT" ) == "" && os .Getenv ("NO_COLOR" ) == ""
2021}
2122
22- // TabBar renders a single-line tab strip. Active uses TabActive (filled
23- // background); inactives use TabInactive.
24- func TabBar (th styles.Theme , labels []string , active int ) string {
23+ // TabBar renders a single-line tab strip. width caps the output; the bar
24+ // degrades to icon-only labels and finally to the active tab alone with
25+ // arrow hints when the full bar would overflow.
26+ func TabBar (th styles.Theme , labels []string , active , width int ) string {
2527 tabs := make ([]Tab , len (labels ))
2628 for i , l := range labels {
2729 tabs [i ] = Tab {Label : l }
2830 }
29- return TabBarRich (th , tabs , active )
31+ return TabBarRich (th , tabs , active , width )
3032}
3133
32- // TabBarRich draws tabs with optional per-tab icons.
33- func TabBarRich ( th styles. Theme , tabs [] Tab , active int ) string {
34- parts := make ([] string , len ( tabs ))
34+ // TabBarRich draws tabs with optional per-tab icons, falling back to a
35+ // compact form when the rendered width exceeds the available terminal width.
36+ func TabBarRich ( th styles. Theme , tabs [] Tab , active , width int ) string {
3537 glyphs := useGlyphs ()
38+ sep := lipgloss .NewStyle ().Foreground (th .Muted ).Render ("│" )
39+
40+ build := func (labels []string ) string {
41+ parts := make ([]string , len (labels ))
42+ for i , label := range labels {
43+ if i == active {
44+ parts [i ] = th .TabActive .Render (label )
45+ } else {
46+ parts [i ] = th .TabInactive .Render (label )
47+ }
48+ }
49+ return strings .Join (parts , sep )
50+ }
51+
52+ full := make ([]string , len (tabs ))
3653 for i , t := range tabs {
3754 label := t .Label
3855 if glyphs && t .Icon != "" {
3956 label = t .Icon + " " + t .Label
4057 }
41- if i == active {
42- parts [i ] = th .TabActive .Render (label )
43- } else {
44- parts [i ] = th .TabInactive .Render (label )
58+ full [i ] = label
59+ }
60+ rendered := build (full )
61+ if width <= 0 || lipgloss .Width (rendered ) <= width {
62+ return rendered
63+ }
64+
65+ if glyphs {
66+ iconsOnly := make ([]string , len (tabs ))
67+ anyIcon := false
68+ for i , t := range tabs {
69+ if t .Icon != "" {
70+ iconsOnly [i ] = t .Icon
71+ anyIcon = true
72+ } else {
73+ iconsOnly [i ] = t .Label
74+ }
75+ }
76+ if anyIcon {
77+ rendered = build (iconsOnly )
78+ if lipgloss .Width (rendered ) <= width {
79+ return rendered
80+ }
4581 }
4682 }
47- sep := lipgloss .NewStyle ().Foreground (th .Muted ).Render ("│" )
48- return strings .Join (parts , sep )
83+
84+ activeLabel := full [active ]
85+ prev := th .Dim .Render ("‹" )
86+ next := th .Dim .Render ("›" )
87+ compact := prev + " " + th .TabActive .Render (activeLabel ) + " " + next
88+ if lipgloss .Width (compact ) <= width {
89+ return compact
90+ }
91+ return th .TabActive .Render (activeLabel )
4992}
0 commit comments