From 1b1021e462b3ba829fba960516d94ce742b70cbf Mon Sep 17 00:00:00 2001 From: Lauri Gates Date: Thu, 25 Jun 2026 09:40:00 +0300 Subject: [PATCH] fix(guide): keep the guide line from collapsing the layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The UI stacks four panes vertically (query editor, guide, completion, JSON viewer). When the guide had no message to show it was rendered from an empty `status::State`, which produces zero rows. The renderer drops zero-row panes entirely, so the guide line vanished and the JSON viewer slid up — then a status message (e.g. "jq failed") brought the pane back and pushed everything down again. On every keystroke that toggled a message on/off, the JSON content jumped up and down, which is distracting. Reserve the guide line as a single blank row when there is no message, so the pane never collapses and the panes below it stay put. The initial render does the same so the layout is stable from the first frame. `--no-hint` is unchanged: the guide stays permanently empty. --- src/guide.rs | 33 ++++++++++++++++++++++++++++++++- src/main.rs | 5 ++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/guide.rs b/src/guide.rs index f3f51eb..0abb5d6 100644 --- a/src/guide.rs +++ b/src/guide.rs @@ -80,6 +80,31 @@ pub fn copy_to_clipboard_message(content: &str) -> GuideMessage { } } +/// A guide state that occupies exactly one (blank) row. +/// +/// Used to reserve the guide line when there is no message to show, so the +/// pane never collapses to zero rows and the panes below it stay put. +fn blank_line() -> status::State { + status::State::new(" ", Severity::Success) +} + +/// Graphemes for the guide pane's initial state. +/// +/// With hints enabled this reserves one blank row so the guide line is present +/// from the first frame — otherwise the first message would shift the panes +/// below it. With `--no-hint` the guide is permanently empty. +pub fn initial_graphemes( + no_hint: bool, + width: u16, + height: u16, +) -> promkit_widgets::core::grapheme::StyledGraphemes { + if no_hint { + Default::default() + } else { + blank_line().create_graphemes(width, height) + } +} + /// Spawn a task that listens for guide actions and updates the guide view accordingly. pub fn start_guide_task( mut action_rx: mpsc::Receiver, @@ -96,7 +121,13 @@ pub fn start_guide_task( Default::default() } else { match action { - GuideAction::Clear => status::State::default().create_graphemes(area.0, area.1), + // Render a single blank line rather than an empty + // state. An empty state produces zero rows, which the + // renderer drops entirely (terminal.rs filters out + // empty panes), collapsing the guide line and shifting + // the JSON viewer up — and back down when a message + // reappears. Reserving one row keeps the layout stable. + GuideAction::Clear => blank_line().create_graphemes(area.0, area.1), GuideAction::Show(message) => message_to_state(message).create_graphemes(area.0, area.1), } }; diff --git a/src/main.rs b/src/main.rs index 15807d7..dc688f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -242,7 +242,10 @@ async fn main() -> anyhow::Result<()> { Index::QueryEditor, query_editor.create_graphemes(terminal_size.0, terminal_size.1), ), - (Index::Guide, StyledGraphemes::default()), + ( + Index::Guide, + guide::initial_graphemes(config.no_hint, terminal_size.0, terminal_size.1), + ), (Index::Completion, StyledGraphemes::default()), (Index::JsonViewer, StyledGraphemes::default()), ]