How to Hide or Show the Target Selector Widget at Runtime in tui-logger

Toggle the target selector visibility in TuiLoggerSmartWidget by sending the HideKey event to the widget state, which flips the internal hide_target boolean flag.

The tui-logger crate by gin66 provides a composite Smart widget that combines log display with an interactive target selector. For applications requiring dynamic layout changes, the library supports runtime visibility control of the target selector component through its event-driven state system.

Understanding the Smart Widget Architecture

The Smart widget (TuiLoggerSmartWidget) renders two distinct components: the log view (TuiLoggerWidget) and the target selector (TuiLoggerTargetWidget). These components share a synchronized state object that determines layout and visibility during each render cycle.

Visibility control relies on a single boolean flag stored in the shared inner state. When this flag changes, the Smart widget automatically adjusts its layout to render either the full two-panel view or a compact single-panel view containing only the logs.

The hide_target Flag Mechanism

The visibility toggle operates through a flag stored in the widget's internal state structure.

Where the State Lives

In src/widget/inner.rs, the TuiWidgetInnerState struct contains the hide_target field at lines 76–78:

pub struct TuiWidgetInnerState {
    // ... other fields ...
    pub(crate) hide_target: bool,   // defaults to false
    // ... other fields ...
}

This flag defaults to false, meaning the target selector is visible by default.

How Toggling Works

The same file handles state transitions via the transition method. At lines 89–91, the HideKey event flips the boolean value:

HideKey => {
    self.hide_target ^= true;   // XOR toggle: true becomes false, false becomes true
}

During rendering in src/widget/smart.rs (lines 229–235), the Smart widget checks this flag to determine the layout:

let hide_target = self.state.lock().hide_target;
if hide_target {
    // render only the log widget
} else {
    // render selector + log side-by-side
}

Runtime Control Methods

You can trigger the visibility toggle through three approaches, depending on your application's architecture.

Method 1: Key Binding (Interactive)

The simplest approach binds a keyboard key to the HideKey event. The official demo in examples/demo.rs (line 92) maps the h key:

// Inside your terminal event loop
match key {
    Key::Char('h') => state.transition(TuiWidgetEvent::HideKey),
    // ... handle other keys ...
}

Each press of h toggles the selector between hidden and visible states.

Method 2: Programmatic Toggle

For non-interactive control, invoke the transition directly on a TuiWidgetState reference:

use tui_logger::{TuiWidgetState, TuiWidgetEvent};

fn toggle_target_selector(state: &mut TuiWidgetState) {
    state.transition(TuiWidgetEvent::HideKey);
}

// Usage
let mut widget_state = TuiWidgetState::new();
toggle_target_selector(&mut widget_state);  // hides selector
toggle_target_selector(&mut widget_state);  // shows selector again

This method integrates with application logic, timers, or remote commands to hide or show the target selector widget at runtime without user input.

Method 3: Direct State Manipulation (Advanced)

For precise control without event abstraction, access the inner state directly through the mutex guard:

use std::sync::Arc;
use parking_lot::Mutex;
use tui_logger::widget::inner::TuiWidgetInnerState;

fn set_target_visibility(state: &TuiWidgetState, hide: bool) {
    let inner: Arc<Mutex<TuiWidgetInnerState>> = state.clone_state();
    let mut guard = inner.lock();
    guard.hide_target = hide;   // true hides selector, false shows it
}

// Usage
let widget_state = TuiWidgetState::new();
set_target_visibility(&widget_state, true);   // explicitly hide
set_target_visibility(&widget_state, false);  // explicitly show

Summary

  • The Smart widget checks hide_target from TuiWidgetInnerState during each render cycle to determine layout.
  • The HideKey event in src/widget/inner.rs toggles this boolean flag using XOR assignment.
  • Key bindings: Map any key to TuiWidgetEvent::HideKey for interactive toggling.
  • Programmatic control: Call state.transition(TuiWidgetEvent::HideKey) from application logic.
  • Direct access: Use state.clone_state() to obtain the mutex guard and set hide_target explicitly.

Frequently Asked Questions

Can I set the initial visibility to hidden when creating the widget?

Yes. After creating TuiWidgetState, immediately send one HideKey event or use the direct state manipulation method to set hide_target to true before the first render. There is no dedicated constructor parameter for initial visibility.

Does hiding the target selector affect log filtering?

No. The hide_target flag controls only the visual rendering of the selector widget. Any active filters or target selections remain in effect and continue filtering the log output even when the selector panel is invisible.

What happens to the layout area when the selector is hidden?

The Smart widget reallocates the full available area to the log view. In src/widget/smart.rs, when hide_target is true, the render method skips the selector layout calculation and passes the entire buffer area to the inner log widget.

Is the HideKey event thread-safe?

Yes. The state uses Arc<Mutex<TuiWidgetInnerState>> (via parking_lot::Mutex), making it safe to call transition() or modify the flag from any thread. The Smart widget acquires the lock during rendering to read the current visibility state.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →