detached fdc7e51

fix(theme): keep stacked title bars compact (#443)

commit
fdc7e51fc3a80e811c9711152a040666fe12c4c9
author
bnema · · 2026-09-20 17:05 UTC
committer
GitHub · · 2026-09-20 17:05 UTC
parent
b79d993
signature
GPG UnverifiedB5690EEEBB952194 The key is unknown
2 files · +28 -8
M internal/ui/theme/css.go +8 -7
@@ -948,7 +948,7 @@ func generatePaneCSS(p Palette) string {
948948 }
949949
950950 // generateStackedPaneCSS creates stacked pane (Zellij-style tabs within panes) styles.
951-// Uses em units for scalable UI.
951+// Text uses scalable units while vertical chrome stays compact in device pixels.
952952 func generateStackedPaneCSS(p Palette) string {
953953 return `/* ===== Stacked Pane Styling ===== */
954954
@@ -958,8 +958,8 @@ func generateStackedPaneCSS(p Palette) string {
958958 background-color: var(--surface-variant);
959959 color: var(--control-text);
960960 border-bottom: 0.0625em solid var(--border);
961- padding: 0.25em 0.5em;
962- min-height: 1.5em;
961+ padding: 4px 0.5em;
962+ min-height: 24px;
963963 }
964964
965965 /* Keep the background stable so --control-text retains its contrast.
@@ -988,15 +988,16 @@ func generateStackedPaneCSS(p Palette) string {
988988 text-decoration-line: underline;
989989 }
990990
991-/* Close button in stacked pane title bar */
991+/* Close button in stacked pane title bar.
992+ * Its vertical footprint is intentionally smaller than the original scale-1 baseline. */
992993 .stacked-pane-close-button {
993994 background: transparent;
994995 border: none;
995996 border-radius: 0.2727em;
996- padding: 0.2727em;
997- margin: 0 0.1364em;
997+ padding: 3px;
998+ margin: 0 2px;
998999 min-width: 1.3636em;
999- min-height: 1.3636em;
1000+ min-height: 15px;
10001001 opacity: 0.4;
10011002 transition: opacity 100ms ease-in-out, background-color 100ms ease-in-out;
10021003 }
@@ -948,7 +948,7 @@ func generatePaneCSS(p Palette) string {
948 }948 }
949 949
950 // generateStackedPaneCSS creates stacked pane (Zellij-style tabs within panes) styles.950 // generateStackedPaneCSS creates stacked pane (Zellij-style tabs within panes) styles.
951-// Uses em units for scalable UI.951+// Text uses scalable units while vertical chrome stays compact in device pixels.
952 func generateStackedPaneCSS(p Palette) string {952 func generateStackedPaneCSS(p Palette) string {
953 return `/* ===== Stacked Pane Styling ===== */953 return `/* ===== Stacked Pane Styling ===== */
954 954
@@ -958,8 +958,8 @@ func generateStackedPaneCSS(p Palette) string {
958 background-color: var(--surface-variant);958 background-color: var(--surface-variant);
959 color: var(--control-text);959 color: var(--control-text);
960 border-bottom: 0.0625em solid var(--border);960 border-bottom: 0.0625em solid var(--border);
961- padding: 0.25em 0.5em;961+ padding: 4px 0.5em;
962- min-height: 1.5em;962+ min-height: 24px;
963 }963 }
964 964
965 /* Keep the background stable so --control-text retains its contrast.965 /* Keep the background stable so --control-text retains its contrast.
@@ -988,15 +988,16 @@ func generateStackedPaneCSS(p Palette) string {
988 text-decoration-line: underline;988 text-decoration-line: underline;
989 }989 }
990 990
991-/* Close button in stacked pane title bar */991+/* Close button in stacked pane title bar.
992+ * Its vertical footprint is intentionally smaller than the original scale-1 baseline. */
992 .stacked-pane-close-button {993 .stacked-pane-close-button {
993 background: transparent;994 background: transparent;
994 border: none;995 border: none;
995 border-radius: 0.2727em;996 border-radius: 0.2727em;
996- padding: 0.2727em;997+ padding: 3px;
997- margin: 0 0.1364em;998+ margin: 0 2px;
998 min-width: 1.3636em;999 min-width: 1.3636em;
999- min-height: 1.3636em;1000+ min-height: 15px;
1000 opacity: 0.4;1001 opacity: 0.4;
1001 transition: opacity 100ms ease-in-out, background-color 100ms ease-in-out;1002 transition: opacity 100ms ease-in-out, background-color 100ms ease-in-out;
1002 }1003 }
M internal/ui/theme/css_test.go +20 -1
@@ -259,7 +259,6 @@ func TestGenerateCSS_AuxiliaryWidgetDimensionsUseScalableUnits(t *testing.T) {
259259 ".loading-skeleton-spinner",
260260 ".loading-skeleton-logo",
261261 ".loading-skeleton-version",
262- ".stacked-pane-close-button",
263262 "progressbar.osd",
264263 "progressbar.osd trough",
265264 "progressbar.osd progress",
@@ -272,6 +271,26 @@ func TestGenerateCSS_AuxiliaryWidgetDimensionsUseScalableUnits(t *testing.T) {
272271 }
273272 }
274273
274+func TestGenerateCSS_StackedPaneTitlebarKeepsCompactVerticalChrome(t *testing.T) {
275+ css := GenerateCSS(DefaultDarkPalette())
276+
277+ titlebar := cssRuleBlock(t, css, ".stacked-pane-titlebar")
278+ assert.Contains(t, titlebar, "padding: 4px 0.5em;")
279+ assert.Contains(t, titlebar, "min-height: 24px;")
280+ assert.NotRegexp(t, `(?m)^\s*(?:padding-(?:top|bottom)|min-height):[^;]*em`, titlebar)
281+
282+ closeButton := cssRuleBlock(t, css, ".stacked-pane-close-button")
283+ assert.Contains(t, closeButton, "padding: 3px;")
284+ assert.Contains(t, closeButton, "margin: 0 2px;")
285+ assert.Contains(t, closeButton, "min-height: 15px;")
286+ assert.NotRegexp(t, `(?m)^\s*(?:padding|margin|min-height):[^;]*em`, closeButton)
287+
288+ // Text and horizontal sizing still follow GTK font scaling.
289+ label := cssRuleBlock(t, css, ".stacked-pane-titlebar label")
290+ assert.Contains(t, label, "font-size: 0.75em;")
291+ assert.Contains(t, closeButton, "min-width: 1.3636em;")
292+}
293+
275294 func TestGenerateCSS_OmniboxOuterBordersUseScalableEmUnits(t *testing.T) {
276295 css := GenerateCSS(DefaultDarkPalette())
277296
@@ -259,7 +259,6 @@ func TestGenerateCSS_AuxiliaryWidgetDimensionsUseScalableUnits(t *testing.T) {
259 ".loading-skeleton-spinner",259 ".loading-skeleton-spinner",
260 ".loading-skeleton-logo",260 ".loading-skeleton-logo",
261 ".loading-skeleton-version",261 ".loading-skeleton-version",
262- ".stacked-pane-close-button",
263 "progressbar.osd",262 "progressbar.osd",
264 "progressbar.osd trough",263 "progressbar.osd trough",
265 "progressbar.osd progress",264 "progressbar.osd progress",
@@ -272,6 +271,26 @@ func TestGenerateCSS_AuxiliaryWidgetDimensionsUseScalableUnits(t *testing.T) {
272 }271 }
273 }272 }
274 273
274+func TestGenerateCSS_StackedPaneTitlebarKeepsCompactVerticalChrome(t *testing.T) {
275+ css := GenerateCSS(DefaultDarkPalette())
276+
277+ titlebar := cssRuleBlock(t, css, ".stacked-pane-titlebar")
278+ assert.Contains(t, titlebar, "padding: 4px 0.5em;")
279+ assert.Contains(t, titlebar, "min-height: 24px;")
280+ assert.NotRegexp(t, `(?m)^\s*(?:padding-(?:top|bottom)|min-height):[^;]*em`, titlebar)
281+
282+ closeButton := cssRuleBlock(t, css, ".stacked-pane-close-button")
283+ assert.Contains(t, closeButton, "padding: 3px;")
284+ assert.Contains(t, closeButton, "margin: 0 2px;")
285+ assert.Contains(t, closeButton, "min-height: 15px;")
286+ assert.NotRegexp(t, `(?m)^\s*(?:padding|margin|min-height):[^;]*em`, closeButton)
287+
288+ // Text and horizontal sizing still follow GTK font scaling.
289+ label := cssRuleBlock(t, css, ".stacked-pane-titlebar label")
290+ assert.Contains(t, label, "font-size: 0.75em;")
291+ assert.Contains(t, closeButton, "min-width: 1.3636em;")
292+}
293+
275 func TestGenerateCSS_OmniboxOuterBordersUseScalableEmUnits(t *testing.T) {294 func TestGenerateCSS_OmniboxOuterBordersUseScalableEmUnits(t *testing.T) {
276 css := GenerateCSS(DefaultDarkPalette())295 css := GenerateCSS(DefaultDarkPalette())
277 296

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