ui: validity indicator rendering + warning theme colour (ADR-0027 step D)
Adds the `[ERR]` / `[WRN]` validity indicator to the input row. `App` gains `input_indicator: Option<Severity>` (the runtime owns its timing — step E) and a pure `input_validity_verdict()` query that runs `input_verdict` in simple mode only (advanced mode is raw SQL, ADR-0027 §7). `render_input_panel` reserves the rightmost six columns of the input row unconditionally (ADR-0027 §4) — a five-column label plus a one-column gap — so the typed command never shifts sideways when the indicator appears or hides. The label renders only when `input_indicator` is set: `[ERR]` in `theme.error`, `[WRN]` in the new amber `theme.warning` (defined for both light and dark themes). The indicator is not yet wired live — `input_indicator` stays `None` until the debounce lands (step E). Covered by a render test and the theme contrast test; the input-panel snapshot is updated for the six-column reservation.
This commit is contained in:
@@ -643,8 +643,37 @@ fn render_input_panel(app: &App, theme: &Theme, frame: &mut Frame<'_>, area: Rec
|
||||
plain_input_spans(&app.input, cursor, theme)
|
||||
}
|
||||
};
|
||||
let paragraph = Paragraph::new(Line::from(spans)).block(block);
|
||||
frame.render_widget(paragraph, area);
|
||||
// ADR-0027 §4: the rightmost six columns of the input row
|
||||
// (a five-column label plus a one-column gap) are reserved
|
||||
// unconditionally, so the text area is always
|
||||
// `inner.width - 6` and the typed command never shifts
|
||||
// sideways when the validity indicator appears or hides.
|
||||
let inner = block.inner(area);
|
||||
frame.render_widget(block, area);
|
||||
let text_area = Rect {
|
||||
width: inner.width.saturating_sub(6),
|
||||
..inner
|
||||
};
|
||||
frame.render_widget(Paragraph::new(Line::from(spans)), text_area);
|
||||
|
||||
if let Some(severity) = app.input_indicator {
|
||||
let (indicator_label, color) = match severity {
|
||||
crate::dsl::walker::Severity::Error => ("[ERR]", theme.error),
|
||||
crate::dsl::walker::Severity::Warning => ("[WRN]", theme.warning),
|
||||
};
|
||||
let label_area = Rect {
|
||||
x: inner.x + inner.width.saturating_sub(5),
|
||||
width: 5.min(inner.width),
|
||||
..inner
|
||||
};
|
||||
frame.render_widget(
|
||||
Paragraph::new(Line::from(Span::styled(
|
||||
indicator_label,
|
||||
Style::default().fg(color).add_modifier(Modifier::BOLD),
|
||||
))),
|
||||
label_area,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert `StyledRun`s into ratatui `Span`s borrowed from
|
||||
|
||||
Reference in New Issue
Block a user