fix(ui): mark sidebar focus with an accent colour, not bold (#25)
The focused sidebar panel border (ADR-0046 DC3) was bright `fg` plus `Modifier::BOLD`. Bold box-drawing glyphs render as broken/gapped line-art in the asciinema cast player and are fragile in some terminals. `panel_border_style` now marks focus with a non-bold accent colour (`theme.mode_simple`, blue); the unfocused border stays muted. Bold is untouched on text spans (titles, key hints) — the constraint is specifically that box-drawing borders carry no bold attribute. Pure style change: the Tier-2 snapshots are text-only so none needed re-accepting; the Tier-1 assertion was updated and a render-level test now checks the rendered border cells carry the accent and no bold. ADR-0046 Amendment 1.
This commit is contained in:
@@ -554,3 +554,27 @@ All tiers green, zero skips; clippy clean (nursery).
|
||||
and is accepted: 90 is the screencast width, real terminals sit well
|
||||
to one side of it, and `Ctrl-O` peek covers the in-between case. The
|
||||
`90` threshold is a tunable constant.
|
||||
|
||||
## Amendment 1 — focus accent is a colour, not bold (2026-06-12)
|
||||
|
||||
Issue #25. DC3's "accent border" on the focused sidebar panel was
|
||||
first implemented as bright `theme.fg` **plus `Modifier::BOLD`** on
|
||||
the box-drawing border. Bold box-drawing glyphs render as broken /
|
||||
gapped line-art in the asciinema player used for the website casts
|
||||
(vertical strokes don't connect to the corner glyphs) and are
|
||||
fragile in some terminals.
|
||||
|
||||
**`panel_border_style` now marks focus with a non-bold accent
|
||||
colour — `theme.mode_simple` (blue) — and never `Modifier::BOLD` on
|
||||
a border.** The unfocused border stays muted `theme.border`. This
|
||||
makes the ADR's "accent border (lazygit convention)" wording
|
||||
literal — it is now a true accent hue rather than bold bright-fg —
|
||||
and is what renders cleanly in casts. Bold remains fine on *text*
|
||||
spans (titles, key hints); the constraint is specifically that
|
||||
box-drawing borders carry no bold attribute.
|
||||
|
||||
Note: this is a pure style change. The Tier-2 snapshots are
|
||||
text-only (`render_to_string` captures cell symbols, not styles),
|
||||
so none needed re-accepting; the Tier-1 `panel_border_style`
|
||||
assertion was updated and a render-level test now checks the actual
|
||||
border cells carry the accent colour and no bold.
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -275,13 +275,15 @@ fn render_nav_sidebar_overlay(app: &mut App, theme: &Theme, frame: &mut Frame<'_
|
||||
render_relationships_panel(app, theme, frame, parts[1]);
|
||||
}
|
||||
|
||||
/// Border style for a sidebar panel: an accented, bold border when it
|
||||
/// holds navigation focus (ADR-0046 DC3), the muted border otherwise.
|
||||
/// Border style for a sidebar panel: a non-bold **accent colour**
|
||||
/// border when it holds navigation focus (ADR-0046 DC3, refined by
|
||||
/// Amendment 1 / issue #25), the muted border otherwise. The focus
|
||||
/// cue is the accent hue, NOT `Modifier::BOLD` — bold box-drawing
|
||||
/// glyphs render as broken/gapped line-art in the asciinema player
|
||||
/// and are fragile in some terminals.
|
||||
fn panel_border_style(theme: &Theme, focused: bool) -> Style {
|
||||
if focused {
|
||||
Style::default()
|
||||
.fg(theme.fg)
|
||||
.add_modifier(Modifier::BOLD)
|
||||
Style::default().fg(theme.mode_simple)
|
||||
} else {
|
||||
Style::default().fg(theme.border)
|
||||
}
|
||||
@@ -3027,16 +3029,76 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn focused_panel_gets_an_accent_border() {
|
||||
// ADR-0046 DC3: the focused sidebar panel is accent-bordered.
|
||||
// ADR-0046 DC3 (Amendment 1, issue #25): the focused sidebar
|
||||
// panel is marked by a non-bold accent COLOUR, not bold. Bold
|
||||
// box-drawing glyphs render as broken/gapped line-art in the
|
||||
// asciinema player (and are fragile in some terminals), so the
|
||||
// focus cue is the accent hue against the muted unfocused
|
||||
// border — never a `Modifier::BOLD` on the border.
|
||||
let theme = Theme::dark();
|
||||
let focused = panel_border_style(&theme, true);
|
||||
let normal = panel_border_style(&theme, false);
|
||||
assert_eq!(focused.fg, Some(theme.fg));
|
||||
assert!(focused.add_modifier.contains(Modifier::BOLD));
|
||||
assert_eq!(focused.fg, Some(theme.mode_simple));
|
||||
assert!(
|
||||
!focused.add_modifier.contains(Modifier::BOLD),
|
||||
"the focused border must NOT be bold (issue #25)",
|
||||
);
|
||||
assert_eq!(normal.fg, Some(theme.border));
|
||||
assert!(!normal.add_modifier.contains(Modifier::BOLD));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn focused_panel_border_cells_are_accent_colour_not_bold() {
|
||||
// Full-stack guard for issue #25: the accent colour (and the
|
||||
// absence of bold) must reach the actual rendered border cells,
|
||||
// not just `panel_border_style` in isolation. With the Tables
|
||||
// panel focused, its box-drawing border cells carry
|
||||
// `theme.mode_simple` and never `Modifier::BOLD`; with no panel
|
||||
// focused, no border cell wears the accent colour.
|
||||
const BOX_DRAWING: &[char] = &['╭', '╮', '╰', '╯', '─', '│'];
|
||||
let is_border = |sym: &str| sym.chars().all(|c| BOX_DRAWING.contains(&c));
|
||||
let theme = Theme::dark();
|
||||
|
||||
let mut app = App::new();
|
||||
app.tables = vec!["Customers".to_string(), "Orders".to_string()];
|
||||
app.nav_focus = NavFocus::SidebarTables;
|
||||
let buf = render_to_buffer(&mut app, &theme, 110, 24);
|
||||
let mut accent_border_cells = 0;
|
||||
for y in 0..buf.area.height {
|
||||
for x in 0..buf.area.width {
|
||||
let cell = &buf[(x, y)];
|
||||
if is_border(cell.symbol()) && cell.fg == theme.mode_simple {
|
||||
accent_border_cells += 1;
|
||||
assert!(
|
||||
!cell.modifier.contains(Modifier::BOLD),
|
||||
"focused border cell at ({x},{y}) must not be bold (issue #25)",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(
|
||||
accent_border_cells > 0,
|
||||
"the focused Tables panel must render accent-coloured border cells",
|
||||
);
|
||||
|
||||
// With nothing focused (Input), no border cell wears the accent.
|
||||
let mut app2 = App::new();
|
||||
app2.tables = vec!["Customers".to_string()];
|
||||
app2.nav_focus = NavFocus::Input;
|
||||
let buf2 = render_to_buffer(&mut app2, &theme, 110, 24);
|
||||
for y in 0..buf2.area.height {
|
||||
for x in 0..buf2.area.width {
|
||||
let cell = &buf2[(x, y)];
|
||||
if is_border(cell.symbol()) {
|
||||
assert_ne!(
|
||||
cell.fg, theme.mode_simple,
|
||||
"no border cell may wear the focus accent when nothing is focused (at {x},{y})",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn focused_tables_panel_scrolls_and_clamps() {
|
||||
// ADR-0046 DC3: more tables than fit → a large offset reveals the
|
||||
|
||||
Reference in New Issue
Block a user