detached cbb0914

feat(config): add ui_scale setting for workspace styling

- Add UIScale field to WorkspaceStylingConfig (default: 1.0)
- Add validation: must be between 0.5 and 3.0
- Wire up to Viper config system for TOML/JSON/YAML support
- Allows users to scale UI elements like title bars (1.2 = 120% size)
commit
cbb091413a0713f3b4849b9e164ee06ce6c960c4
author
bnema · · 2025-11-16 18:36 UTC
committer
bnema · · 2025-11-16 17:59 UTC
parent
92941be
signature
unsigned
3 files · +8 -0
M internal/config/config.go +3 -0
@@ -313,6 +313,8 @@ type WorkspaceStylingConfig struct {
313313 TransitionDuration int `mapstructure:"transition_duration" yaml:"transition_duration" json:"transition_duration"`
314314 // BorderRadius in pixels for pane border corners
315315 BorderRadius int `mapstructure:"border_radius" yaml:"border_radius" json:"border_radius"`
316+ // UIScale is a multiplier for UI elements like title bars (1.0 = 100%, 1.2 = 120%)
317+ UIScale float64 `mapstructure:"ui_scale" yaml:"ui_scale" json:"ui_scale"`
316318 }
317319
318320 // Manager handles configuration loading, watching, and reloading.
@@ -711,6 +713,7 @@ func (m *Manager) setDefaults() {
711713 m.viper.SetDefault("workspace.styling.pane_mode_border_color", defaults.Workspace.Styling.PaneModeBorderColor)
712714 m.viper.SetDefault("workspace.styling.transition_duration", defaults.Workspace.Styling.TransitionDuration)
713715 m.viper.SetDefault("workspace.styling.border_radius", defaults.Workspace.Styling.BorderRadius)
716+ m.viper.SetDefault("workspace.styling.ui_scale", defaults.Workspace.Styling.UIScale)
714717 }
715718
716719 // createDefaultConfig creates a default configuration file.
@@ -313,6 +313,8 @@ type WorkspaceStylingConfig struct {
313 TransitionDuration int `mapstructure:"transition_duration" yaml:"transition_duration" json:"transition_duration"`313 TransitionDuration int `mapstructure:"transition_duration" yaml:"transition_duration" json:"transition_duration"`
314 // BorderRadius in pixels for pane border corners314 // BorderRadius in pixels for pane border corners
315 BorderRadius int `mapstructure:"border_radius" yaml:"border_radius" json:"border_radius"`315 BorderRadius int `mapstructure:"border_radius" yaml:"border_radius" json:"border_radius"`
316+ // UIScale is a multiplier for UI elements like title bars (1.0 = 100%, 1.2 = 120%)
317+ UIScale float64 `mapstructure:"ui_scale" yaml:"ui_scale" json:"ui_scale"`
316 }318 }
317 319
318 // Manager handles configuration loading, watching, and reloading.320 // Manager handles configuration loading, watching, and reloading.
@@ -711,6 +713,7 @@ func (m *Manager) setDefaults() {
711 m.viper.SetDefault("workspace.styling.pane_mode_border_color", defaults.Workspace.Styling.PaneModeBorderColor)713 m.viper.SetDefault("workspace.styling.pane_mode_border_color", defaults.Workspace.Styling.PaneModeBorderColor)
712 m.viper.SetDefault("workspace.styling.transition_duration", defaults.Workspace.Styling.TransitionDuration)714 m.viper.SetDefault("workspace.styling.transition_duration", defaults.Workspace.Styling.TransitionDuration)
713 m.viper.SetDefault("workspace.styling.border_radius", defaults.Workspace.Styling.BorderRadius)715 m.viper.SetDefault("workspace.styling.border_radius", defaults.Workspace.Styling.BorderRadius)
716+ m.viper.SetDefault("workspace.styling.ui_scale", defaults.Workspace.Styling.UIScale)
714 }717 }
715 718
716 // createDefaultConfig creates a default configuration file.719 // createDefaultConfig creates a default configuration file.
M internal/config/defaults.go +2 -0
@@ -32,6 +32,7 @@ const (
3232 defaultPaneModeBorderColor = "#FFA500" // Orange for pane mode indicator
3333 defaultTransitionDuration = 120
3434 defaultBorderRadius = 0
35+ defaultUIScale = 1.0 // UI scale multiplier (1.0 = 100%, 1.2 = 120%)
3536 )
3637
3738 // getDefaultLogDir returns the default log directory, falls back to empty string on error
@@ -183,6 +184,7 @@ func DefaultConfig() *Config {
183184 PaneModeBorderColor: defaultPaneModeBorderColor,
184185 TransitionDuration: defaultTransitionDuration,
185186 BorderRadius: defaultBorderRadius,
187+ UIScale: defaultUIScale,
186188 },
187189 },
188190 ContentFilteringWhitelist: []string{
@@ -32,6 +32,7 @@ const (
32 defaultPaneModeBorderColor = "#FFA500" // Orange for pane mode indicator32 defaultPaneModeBorderColor = "#FFA500" // Orange for pane mode indicator
33 defaultTransitionDuration = 12033 defaultTransitionDuration = 120
34 defaultBorderRadius = 034 defaultBorderRadius = 0
35+ defaultUIScale = 1.0 // UI scale multiplier (1.0 = 100%, 1.2 = 120%)
35 )36 )
36 37
37 // getDefaultLogDir returns the default log directory, falls back to empty string on error38 // getDefaultLogDir returns the default log directory, falls back to empty string on error
@@ -183,6 +184,7 @@ func DefaultConfig() *Config {
183 PaneModeBorderColor: defaultPaneModeBorderColor,184 PaneModeBorderColor: defaultPaneModeBorderColor,
184 TransitionDuration: defaultTransitionDuration,185 TransitionDuration: defaultTransitionDuration,
185 BorderRadius: defaultBorderRadius,186 BorderRadius: defaultBorderRadius,
187+ UIScale: defaultUIScale,
186 },188 },
187 },189 },
188 ContentFilteringWhitelist: []string{190 ContentFilteringWhitelist: []string{
M internal/config/validation.go +3 -0
@@ -79,6 +79,9 @@ func validateConfig(config *Config) error {
7979 if config.Workspace.Styling.BorderRadius < 0 {
8080 validationErrors = append(validationErrors, "workspace.styling.border_radius must be non-negative")
8181 }
82+ if config.Workspace.Styling.UIScale < 0.5 || config.Workspace.Styling.UIScale > 3.0 {
83+ validationErrors = append(validationErrors, "workspace.styling.ui_scale must be between 0.5 and 3.0")
84+ }
8285
8386 // Validate pane mode timeout
8487 if config.Workspace.PaneMode.TimeoutMilliseconds < 0 {
@@ -79,6 +79,9 @@ func validateConfig(config *Config) error {
79 if config.Workspace.Styling.BorderRadius < 0 {79 if config.Workspace.Styling.BorderRadius < 0 {
80 validationErrors = append(validationErrors, "workspace.styling.border_radius must be non-negative")80 validationErrors = append(validationErrors, "workspace.styling.border_radius must be non-negative")
81 }81 }
82+ if config.Workspace.Styling.UIScale < 0.5 || config.Workspace.Styling.UIScale > 3.0 {
83+ validationErrors = append(validationErrors, "workspace.styling.ui_scale must be between 0.5 and 3.0")
84+ }
82 85
83 // Validate pane mode timeout86 // Validate pane mode timeout
84 if config.Workspace.PaneMode.TimeoutMilliseconds < 0 {87 if config.Workspace.PaneMode.TimeoutMilliseconds < 0 {

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 8

Tags 42

↑↓ moveenter openesc close