summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-07-31 21:54:27 -0300
committerGabriel Schneider <[email protected]>2026-08-01 15:02:08 -0300
commit6002422d04f1120ba7b0c5169d6a4ff01c1b5aff (patch)
tree0952ad04aeafdd0b9e7a8e20e0b6b9ceae409862 /src
parent98418fd7ddb525b75b376e9e7d970be2a9f62ff5 (diff)
downloadpardes-6002422d04f1120ba7b0c5169d6a4ff01c1b5aff.tar.gz
pardes-6002422d04f1120ba7b0c5169d6a4ff01c1b5aff.zip
the scrollbar is one column, not two
Diffstat (limited to 'src')
-rw-r--r--src/config.zig7
-rw-r--r--src/pardes.zig34
2 files changed, 35 insertions, 6 deletions
diff --git a/src/config.zig b/src/config.zig
index 0db1d344..0dc12f98 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -392,7 +392,12 @@ pub const PREFIX_W: u16 = 5;
/// above/below the cursor (clamped at file boundaries and short panes), and
/// the same count of COLUMNS horizontally
pub const scroll_off = 3;
-/// the pane's left chrome: scrollbar + the layout box in the tag row
+/// the pane's left chrome: scrollbar + the layout box in the tag row. The
+/// scrollbar PAINTS only the first of these columns; the second is the pane's
+/// own background, so the bar reads as one column with a column of page
+/// between it and the text. Layout is untouched by that — the gutter is still
+/// GUTTER columns and a click anywhere in them still scrolls; only the ink
+/// narrowed. A half-block glyph in the second column was tried and rejected.
pub const GUTTER: u16 = 2;
/// a pane never shrinks past this (the h-handle can still take it to its tag
/// row alone, which is BOX_H and a structural fact, not this)
diff --git a/src/pardes.zig b/src/pardes.zig
index 760a452f..4dd35758 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -7005,6 +7005,11 @@ pub const Pardes = struct {
const th = p.theme();
const tx = r.x + config.GUTTER; // text area (tag + body), right of the gutter
const tw = r.w - config.GUTTER;
+ // the pane's own background, for everything that has to read as "no
+ // chrome here": the body text, and the blank right half of the
+ // scrollbar's second column. `.default` means the host terminal's own
+ // background, which is what a themeless dark pane wants.
+ const pane_bg: Color = if (th.bg) |c| .{ .rgb = c } else .default;
// text area resets to terminal-default cells (vaxis clear semantics);
// light themes paint the page over it.
@@ -7059,7 +7064,10 @@ pub const Pardes = struct {
p.drawImage(pane, r, tx, tw);
const box_bg2 = if (active) th.box else th.box_dim;
s.fill(r.x, r.y, config.GUTTER, BOX_H, .{ .bg = .{ .rgb = box_bg2 } });
- if (r.h > BOX_H) s.fill(r.x, r.y + BOX_H, config.GUTTER, r.h - BOX_H, .{ .bg = .{ .rgb = th.scroll_track } });
+ // thumbless, but the same one column as the real scrollbar below —
+ // that is the whole point of drawing it
+ s.fill(r.x, r.y + BOX_H, 1, r.h -| BOX_H, .{ .bg = .{ .rgb = th.scroll_track } });
+ s.fill(r.x + 1, r.y + BOX_H, 1, r.h -| BOX_H, .{ .bg = pane_bg });
return;
}
@@ -7067,7 +7075,7 @@ pub const Pardes = struct {
const body_h = if (r.h > BOX_H) r.h - BOX_H else 0;
const body_style: CellStyle = .{
.fg = if (th.fg) |c| .{ .rgb = c } else .default,
- .bg = if (th.bg) |c| .{ .rgb = c } else .default,
+ .bg = pane_bg,
};
const tz_body = tracy.zone(@src(), "bodyText");
const body = try p.bodyText(arena, pane);
@@ -7207,11 +7215,27 @@ pub const Pardes = struct {
}
}
- // gutter: move box on top, scrollbar track + thumb below
+ // gutter: move box on top, scrollbar track + thumb below.
+ //
+ // The bar is ONE column: column 1 is the track/thumb, column 2 is the
+ // pane's own background. That second fill is not optional — render()
+ // pre-fills the whole surface with scroll_track so the gaps between
+ // panes read as chrome, so a column left unpainted here keeps the
+ // track colour and the bar looks two wide again.
+ //
+ // The move box above stays the full GUTTER. It is a target you drag,
+ // not a gauge you read, and its whole width is the affordance — the
+ // step where the box ends and the narrower bar begins is the one place
+ // on screen that says those are two different pieces of chrome.
+ //
+ // Nothing here touches layout or hit-testing: the gutter is still
+ // config.GUTTER columns and the click handlers still scroll on any of
+ // them, so the blank column is still live. Only the ink narrowed.
const box_bg = if (active) th.box else th.box_dim;
s.fill(r.x, r.y, config.GUTTER, BOX_H, .{ .bg = .{ .rgb = box_bg } });
if (r.h > BOX_H) {
- s.fill(r.x, r.y + BOX_H, config.GUTTER, r.h - BOX_H, .{ .bg = .{ .rgb = th.scroll_track } });
+ s.fill(r.x, r.y + BOX_H, 1, r.h - BOX_H, .{ .bg = .{ .rgb = th.scroll_track } });
+ s.fill(r.x + 1, r.y + BOX_H, 1, r.h - BOX_H, .{ .bg = pane_bg });
const sb: struct { total: usize, offset: usize, len: usize } = if (pane.file) |*f| .{
.total = file_pane.nlines(p.gpa, f),
.offset = f.scroll,
@@ -7226,7 +7250,7 @@ pub const Pardes = struct {
const pos = (track_h * sb.offset) / total;
var sy: usize = pos;
while (sy < track_h and sy < pos + len) : (sy += 1) {
- s.fill(r.x, r.y + BOX_H + @as(u16, @intCast(sy)), config.GUTTER, 1, .{ .bg = .{ .rgb = th.scroll_thumb } });
+ s.fill(r.x, r.y + BOX_H + @as(u16, @intCast(sy)), 1, 1, .{ .bg = .{ .rgb = th.scroll_thumb } });
}
}
}