feat(ui): flat filled rectangles for demo overlays (#22, ADR-0047 D4)
Render the keystroke badge and step caption as a solid yellow rectangle with no border glyphs and a one-cell text margin, instead of a rounded-border box — deliberately unlike the app's bordered panels so the demo overlays read as a distinct, eye-catching callout. Shared fill_overlay_rect helper (borderless Block fill + inset Paragraph). Snapshots regenerated; ADR-0047 D4 wording updated.
This commit is contained in:
+6
-6
@@ -11,12 +11,12 @@ expression: snapshot
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ ╭───────╮ │
|
||||
│ │ [TAB] │ │
|
||||
│ ╰───────╯ │
|
||||
│ ╭─────────────────────╮ │
|
||||
│ │ Completing the name │ │
|
||||
│ ╰─────────────────────╯ │
|
||||
│ │
|
||||
│ [TAB] │
|
||||
│ │
|
||||
│ │
|
||||
│ Completing the name │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭ SIMPLE ────────────────────────────────────────────────────────────────────────────────╮
|
||||
|
||||
@@ -14,9 +14,9 @@ expression: snapshot
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ ╭─────────╮ │
|
||||
│ │ [ENTER] │ │
|
||||
│ ╰─────────╯ │
|
||||
│ │
|
||||
│ [ENTER] │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭ SIMPLE ────────────────────────────────────────────────────────────────────────────────╮
|
||||
|
||||
@@ -14,9 +14,9 @@ expression: snapshot
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ ╭───────╮ │
|
||||
│ │ [TAB] │ │
|
||||
│ ╰───────╯ │
|
||||
│ │
|
||||
│ [TAB] │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭ SIMPLE ────────────────────────────────────────────────────────────────────────────────╮
|
||||
|
||||
@@ -14,9 +14,9 @@ expression: snapshot
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ ╭──────────────────────────────────────────╮ │
|
||||
│ │ Now press Tab to complete the table name │ │
|
||||
│ ╰──────────────────────────────────────────╯ │
|
||||
│ │
|
||||
│ Now press Tab to complete the table name │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭ SIMPLE ────────────────────────────────────────────────────────────────────────────────╮
|
||||
|
||||
@@ -12,11 +12,11 @@ expression: snapshot
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ ╭──────────────────────────────────────────╮ │
|
||||
│ │ This is a deliberately long step caption │ │
|
||||
│ │ that must wrap onto several lines and │ │
|
||||
│ │ then be clipped to three with an… │ │
|
||||
│ ╰──────────────────────────────────────────╯ │
|
||||
│ │
|
||||
│ This is a deliberately long step caption │
|
||||
│ that must wrap onto several lines and │
|
||||
│ then be clipped to three with an… │
|
||||
│ │
|
||||
│ │
|
||||
╰────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
╭ SIMPLE ────────────────────────────────────────────────────────────────────────────────╮
|
||||
|
||||
@@ -152,15 +152,31 @@ fn render_demo_overlays(app: &App, frame: &mut Frame<'_>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Paint a flat filled overlay rectangle — a solid yellow block with no
|
||||
/// border glyphs (ADR-0047 D4) — and lay `body` inside a one-cell
|
||||
/// margin. The borderless solid block is deliberately *unlike* the app's
|
||||
/// bordered panels, so the demo overlays read as a distinct callout.
|
||||
fn fill_overlay_rect(rect: Rect, body: String, frame: &mut Frame<'_>) {
|
||||
frame.render_widget(ratatui::widgets::Clear, rect);
|
||||
// `Block` with no borders fills the whole rect with the overlay
|
||||
// background (same mechanism as `paint_background`).
|
||||
frame.render_widget(Block::default().style(demo_overlay_style()), rect);
|
||||
let inner = rect.inner(Margin {
|
||||
horizontal: 1,
|
||||
vertical: 1,
|
||||
});
|
||||
frame.render_widget(Paragraph::new(body).style(demo_overlay_style()), inner);
|
||||
}
|
||||
|
||||
/// A small high-contrast keystroke badge (`[TAB]`, `[ENTER]`, …) inset
|
||||
/// one cell from the bottom-right of `area` (ADR-0047 D2/D4). When a
|
||||
/// caption box is present (`above`), the badge sits directly on top of
|
||||
/// it, right-aligned; otherwise it takes the bottom-right corner.
|
||||
/// Skipped rather than overflowing if it cannot fit.
|
||||
/// one cell from the bottom-right of `area` (ADR-0047 D2/D4) — the label
|
||||
/// on a flat yellow rectangle with a one-cell margin. When a caption box
|
||||
/// is present (`above`), the badge sits directly on top of it, right
|
||||
/// edges aligned; otherwise it takes the bottom-right corner. Skipped
|
||||
/// rather than overflowing if it cannot fit.
|
||||
fn render_badge_box(label: &str, area: Rect, above: Option<Rect>, frame: &mut Frame<'_>) {
|
||||
// ` [LABEL] ` (one pad each side) inside a rounded border.
|
||||
let box_w = label.chars().count() as u16 + 4;
|
||||
let box_h = 3;
|
||||
let box_w = label.chars().count() as u16 + 2; // one-cell margin each side
|
||||
let box_h = 3; // text row + a margin row above and below
|
||||
if box_w + 1 > area.width {
|
||||
return;
|
||||
}
|
||||
@@ -180,34 +196,25 @@ fn render_badge_box(label: &str, area: Rect, above: Option<Rect>, frame: &mut Fr
|
||||
area.y + area.height - box_h - 1
|
||||
}
|
||||
};
|
||||
let rect = Rect { x, y, width: box_w, height: box_h };
|
||||
let block = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Rounded)
|
||||
.style(demo_overlay_style());
|
||||
let para = Paragraph::new(format!(" {label} "))
|
||||
.style(demo_overlay_style())
|
||||
.block(block);
|
||||
frame.render_widget(ratatui::widgets::Clear, rect);
|
||||
frame.render_widget(para, rect);
|
||||
fill_overlay_rect(Rect { x, y, width: box_w, height: box_h }, label.to_string(), frame);
|
||||
}
|
||||
|
||||
/// A step-caption box inset one cell from the bottom-right of `area`
|
||||
/// (ADR-0047 D3/D4): the text word-wrapped to at most 3 lines within a
|
||||
/// corner-sized width, bold black on yellow. Returns the rect it drew,
|
||||
/// or `None` if it was too small to place (so the badge can fall back to
|
||||
/// the bottom-right corner).
|
||||
/// corner-sized width, bold black on a flat yellow rectangle. Returns
|
||||
/// the rect it drew, or `None` if it was too small to place (so the
|
||||
/// badge can fall back to the bottom-right corner).
|
||||
fn render_caption_box(text: &str, area: Rect, frame: &mut Frame<'_>) -> Option<Rect> {
|
||||
// Content width capped so the box stays corner-sized; the caption
|
||||
// wraps to ≤ 3 lines and ellipsises beyond (D4).
|
||||
let content_w = 40.min(area.width.saturating_sub(6)) as usize;
|
||||
let content_w = 40.min(area.width.saturating_sub(4)) as usize;
|
||||
if content_w < 4 {
|
||||
return None; // output too narrow for a useful caption
|
||||
}
|
||||
let lines = clamp_wrapped(text, content_w, 3);
|
||||
let inner_w = lines.iter().map(|l| l.chars().count()).max().unwrap_or(0);
|
||||
let box_w = inner_w as u16 + 4; // 2 border + 1 pad each side
|
||||
let box_h = lines.len() as u16 + 2; // 2 border
|
||||
let box_w = inner_w as u16 + 2; // one-cell margin each side
|
||||
let box_h = lines.len() as u16 + 2; // text rows + a margin row above and below
|
||||
if box_w + 1 > area.width || box_h + 1 > area.height {
|
||||
return None;
|
||||
}
|
||||
@@ -217,18 +224,7 @@ fn render_caption_box(text: &str, area: Rect, frame: &mut Frame<'_>) -> Option<R
|
||||
width: box_w,
|
||||
height: box_h,
|
||||
};
|
||||
let body = lines
|
||||
.iter()
|
||||
.map(|l| format!(" {l}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let block = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Rounded)
|
||||
.style(demo_overlay_style());
|
||||
let para = Paragraph::new(body).style(demo_overlay_style()).block(block);
|
||||
frame.render_widget(ratatui::widgets::Clear, rect);
|
||||
frame.render_widget(para, rect);
|
||||
fill_overlay_rect(rect, lines.join("\n"), frame);
|
||||
Some(rect)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user