Skip to content

GTK chrome: close the visual gap with VS Code — type size, vertical rhythm, tab/breadcrumb metrics #699

Description

@JDonaghy

Goal

Close the visual gap between vimcode's GTK chrome and VS Code. Side-by-side screenshot
(vimcode top, VS Code bottom, same screen/DPI, same file open) shows the difference is
almost entirely type size and vertical rhythm in the chrome, not colour and not
layout structure. Most of it is a handful of metric constants, so the payoff-to-risk
ratio is high.

This is an audit + parent issue. It is deliberately not one worker's dispatch —
see "Splitting" at the bottom.

What the screenshot shows

Reading top (vimcode) against bottom (VS Code):

  • Everything in vimcode's chrome is roughly 15–25% larger. The menu bar, tab
    labels, breadcrumb and explorer rows all sit on a bigger grid. VS Code fits ~13
    explorer rows in the vertical space vimcode uses for ~7.
  • The breadcrumb is as large and as bright as the code itself. In VS Code it is
    visibly smaller and dimmer than the editor text, and carries a file icon on the
    leaf segment.
  • Tabs carry ordinal prefixes (1: main.rs, 2: mod.rs) and no file-type icon.
    VS Code shows a coloured language icon + bare filename, and marks the active tab
    with a top accent line.
  • Menu mnemonics are underlined permanently (F̲ile E̲dit V̲iew). VS Code only
    reveals them while Alt is held.
  • No indent guides in the editor; VS Code draws them by default.
  • No panel separator borders. VS Code Dark Modern puts a 1px #2B2B2B line
    between activity bar / sidebar / editor; vimcode's panes butt together at the same
    background value, so the sidebar reads as part of the editor.
  • Line numbers are uniformly bright. VS Code dims them (#858585) and brightens
    only the cursor's line.
  • Activity-bar icons read slightly oversized against VS Code's.

The fixes, in priority order

Tier 1 — metric constants (highest payoff, smallest diff, vimcode-side only)

# Change Now Target Where
1 Explorer row height 28.0 px 22 px (VS Code list.rowHeight) src/gtk/mod.rs:1572 (explorer_row_height_cell)
2 Decouple tab-bar height from the editor font ceil(line_height * 1.6) 35 px fixed, independent of font_size src/gtk/mod.rs:1416, and the three duplicate sites at :2647, :10207, :10346
3 Decouple the breadcrumb row from the editor font + line_height when settings.breadcrumbs 22 px row at ~12px text, dimmed fg same sites as #2
4 Drop the ordinal prefix from tab labels " {i+1}: {name} " "{name}" src/render.rs:10017 (+ the two [No Name] arms at :10022, :10025)
5 Stop underlining menu mnemonics unconditionally every item gets & pass & only while Alt is held, or drop it src/render.rs:3265 (format!("&{name}"))
6 Turn indent guides on by default setting exists, evidently off default on src/core/settings.rs (the indent_guides default)

Items 2/3/4 travel together — they are what makes the top of the window feel oversized.
Note item 4 has a hit-testing consequence: quadraui::TabItem's doc says backends locate
the filename "after the last \": \"" to underline it, so removing the prefix needs the
tab-bar underline/hit path re-checked, not just the format string.

Tier 2 — type stack and colour tokens (vimcode-side)

# Change Now Target Where
7 UI font stack "Segoe UI, Ubuntu, Droid Sans, Sans" @ ui_font_size 10pt put the real system UI font first — system-ui/Cantarell/Ubuntu — before falling through to generic Sans. On this Linux box neither Segoe UI nor Droid Sans resolves, so it lands on DejaVu Sans, which is wider and has a taller x-height than VS Code's result at the same nominal size src/gtk/mod.rs:64 (UI_FONT_FAMILY), default in src/core/settings.rs:728
8 Line-number foreground uniform dim inactive (#858585), bright on the cursor line theme tokens
9 Panel separator borders none 1px #2B2B2B between activity bar / sidebar / editor theme + GTK paint
10 Breadcrumb foreground ~code brightness dimmed, distinct from editor text theme tokens

Item 7 is a judgement call about which family, not a mechanical swap — worth eyeballing
before/after rather than trusting the constant.

Tier 3 — needs a quadraui change first (see the seam note)

# Change Why it's quadraui-side
11 Per-tab file-type icon quadraui::TabItem has no icon fieldquadraui/src/primitives/tab_bar.rs:114-132 is label / is_active / is_dirty / is_preview / is_closable only
12 Active-tab top accent line the GTK tab-bar rasteriser distinguishes active by bg/fg only (quadraui/src/gtk/tab_bar.rs:177,187,197)
13 Activity-bar icon size hardcoded "Symbols Nerd Font, monospace 20" ≈ 26.7px vs VS Code's 24px codicons — quadraui/src/gtk/activity_bar.rs:72. The 48px row itself (:22) already matches VS Code, so only the glyph size is off

Seam note — do not edit the pin

Cargo.toml:62 pins quadraui to a git rev
(29b98d6647ed808236dc3a11e97cd5d070192e91). Tier 3 therefore cannot land from a vimcode
branch: it needs a quadraui PR merged, released, and the pin bumped deliberately.
Do not edit that rev as a shortcut. Tiers 1 and 2 are entirely vimcode-side and can
ship without touching quadraui at all — which is the argument for doing them first and
measuring what gap is actually left.

Acceptance

Per this repo's black-box rule, assert on rendered output via GtkDriver
(src/gtk/testing.rs) — it paints into in-memory Cairo surfaces, so metrics are directly
assertable:

  • explorer row pitch == 22 px
  • tab-bar height stays 35 px across at least two different settings.font_size values
    (this is the assertion that actually pins the decoupling in v0.3.0: TUI-only binary (vcd) #2/v0.3.1: IDE polish, auto-pairs, build fixes #3 — a single-font-size
    test passes with the bug reinstated)
  • breadcrumb row height and text size independent of font_size
  • a tab label renders as main.rs, not 1: main.rs
  • menu-bar items render with no underline when Alt is not held

A screenshot comparison is not a test — it is the reason for the issue, not the evidence
that it is fixed.

Out of scope

VS Code features visible in the screenshot that are not styling and should not be
smuggled in here: the "Open Editors" sidebar section, the inline git-blame annotation,
the minimap, the command-center pill in the title bar, and the editor's syntax-token
palette (a separate theme-fidelity question).

Splitting

Tier 1 is six independent one-liner-ish changes over two files and should be a single
dispatch. Tier 2 is a second. Tier 3 is a quadraui issue plus a pin bump, and should not
be queued until Tiers 1–2 have shipped and the remaining gap has been re-photographed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions