workspace_css.go RawHistoryFolder
1// workspace_css.go - CSS generation and styling for workspace panes
2package browser
3
4import (
5 "fmt"
6 "strings"
7
8 "github.com/bnema/dumber/internal/config"
9 "github.com/bnema/dumber/pkg/webkit"
10)
11
12// Helper functions for stacked pane CSS colors
13
14// getStackTitleBg returns the background color for stack titles based on theme
15func getStackTitleBg(isDark bool) string {
16 if isDark {
17 return "#404040"
18 }
19 return "#f0f0f0"
20}
21
22// getStackTitleHoverBg returns the hover background color for stack titles based on theme
23func getStackTitleHoverBg(isDark bool) string {
24 if isDark {
25 return "#505050"
26 }
27 return "#e0e0e0"
28}
29
30// getStackTitleTextColor returns the text color for stack titles based on theme
31func getStackTitleTextColor(isDark bool) string {
32 if isDark {
33 return "#ffffff"
34 }
35 return "#333333"
36}
37
38// getActivePaneBorderColor returns the border color for active panes based on config and theme
39func getActivePaneBorderColor(styling config.WorkspaceStylingConfig, isDark bool) string {
40 // Use configured border color if set
41 if styling.BorderColor != "" {
42 // Check if it's a GTK theme variable (starts with @)
43 if strings.HasPrefix(styling.BorderColor, "@") {
44 return styling.BorderColor
45 }
46 // Return the configured color as-is (could be hex, rgb, etc.)
47 return styling.BorderColor
48 }
49
50 // Fallback to hardcoded colors based on theme
51 if isDark {
52 return "#4A90E2" // Deeper blue pastel for dark theme
53 }
54 return "#87CEEB" // Sky blue pastel for light theme
55}
56
57// generateWorkspaceCSS generates the complete CSS for workspace panes and stacked panes
58func (wm *WorkspaceManager) generateWorkspaceCSS() string {
59 cfg := config.Get()
60 styling := cfg.Workspace.Styling
61
62 // Get appropriate colors based on GTK theme preference
63 var inactiveBorderColor, windowBackgroundColor string
64 isDark := webkit.PrefersDarkTheme()
65 if isDark {
66 inactiveBorderColor = "#333333" // Dark border for dark theme
67 windowBackgroundColor = "#2b2b2b" // Dark window background
68 } else {
69 inactiveBorderColor = "#dddddd" // Light border for light theme
70 windowBackgroundColor = "#ffffff" // Light window background
71 }
72
73 activeBorderColor := getActivePaneBorderColor(styling, isDark)
74
75 css := fmt.Sprintf(`window {
76 background-color: %s;
77 }
78
79 /* Base pane styling - transparent outline for smooth transitions */
80 .workspace-pane, .stacked-pane-container {
81 outline: 2px solid transparent;
82 outline-offset: -2px;
83 transition: outline-color %dms ease-in-out;
84 }
85
86 /* Active pane border styling using outline (no layout impact) */
87 .workspace-pane-active {
88 outline-color: %s;
89 }
90
91 /* Stacked panes styling */
92 .stacked-pane-container {
93 background-color: %s;
94 border-radius: %dpx;
95 }
96
97 /* Active stacked pane container gets the outline color */
98 .stacked-pane-container.workspace-pane-active {
99 outline-color: %s;
100 }
101
102 .stacked-pane-title {
103 background-color: %s;
104 border-bottom: 1px solid %s;
105 padding: 4px 8px;
106 min-height: 24px;
107 transition: background-color %dms ease-in-out;
108 }
109
110 .stacked-pane-title:hover {
111 background-color: %s;
112 }
113
114 .stacked-pane-title-text {
115 font-size: 12px;
116 color: %s;
117 font-weight: 500;
118 }
119
120 .stacked-pane-favicon {
121 margin-right: 4px;
122 }
123
124 .stacked-pane-active {
125 /* Active pane is fully visible */
126 }
127
128 .stacked-pane-collapsed {
129 /* Collapsed panes are hidden - handled in code via widget visibility */
130 }`,
131 windowBackgroundColor, // window background
132 styling.TransitionDuration, // base pane outline transition
133 activeBorderColor, // workspace-pane-active outline-color
134 windowBackgroundColor, // stacked-pane-container background
135 styling.BorderRadius, // stacked-pane-container border-radius
136 activeBorderColor, // stacked-pane-container.workspace-pane-active outline-color
137 getStackTitleBg(isDark), // stacked-pane-title background
138 inactiveBorderColor, // stacked-pane-title border-bottom
139 styling.TransitionDuration, // stacked-pane-title transition
140 getStackTitleHoverBg(isDark), // stacked-pane-title:hover background
141 getStackTitleTextColor(isDark), // stacked-pane-title-text color
142 )
143
144 return css
145}
146
147// generateStackedPaneCSS generates the CSS for stacked pane title bars (deprecated - use generateWorkspaceCSS)
148func (wm *WorkspaceManager) generateStackedPaneCSS() string {
149 // Delegate to the new comprehensive CSS generator
150 return wm.generateWorkspaceCSS()
151}
152
153// Global CSS provider tracking to prevent duplication
154var (
155 globalCSSInitialized bool
156 globalCSSContent string
157)
158
159// ensureWorkspaceStyles ensures that CSS styles are applied for workspace panes
160// Improved to prevent CSS provider duplication by using global CSS tracking
161func (wm *WorkspaceManager) ensureWorkspaceStyles() {
162 if wm == nil {
163 return
164 }
165
166 // Generate CSS content
167 workspaceCSS := wm.generateWorkspaceCSS()
168
169 // Only apply CSS if it hasn't been applied globally or if content changed
170 if !globalCSSInitialized || globalCSSContent != workspaceCSS {
171 webkit.AddCSSProvider(workspaceCSS)
172 globalCSSInitialized = true
173 globalCSSContent = workspaceCSS
174 }
175
176 wm.cssInitialized = true
177}
178
179// ensureStackedPaneStyles ensures that CSS styles are applied for stacked panes (deprecated - use ensureWorkspaceStyles)
180func (wm *WorkspaceManager) ensureStackedPaneStyles() {
181 wm.ensureWorkspaceStyles()
182}