Skip to main content

Context

Struct Context 

Source
pub struct Context { /* private fields */ }
Expand description

The main rendering context passed to your closure each frame.

Provides all methods for building UI: text, containers, widgets, and event handling. You receive a &mut Context on every frame and describe what to render by calling its methods. SLT collects those calls, lays them out with flexbox, diffs against the previous frame, and flushes only changed cells.

§Example

slt::run(|ui: &mut slt::Context| {
    if ui.key('q') { ui.quit(); }
    ui.text("Hello, world!").bold();
});

Implementations§

Source§

impl Context

Source

pub fn gauge(&mut self, ratio: f64) -> Gauge<'_>

Begin building a block-fill progress bar with optional centered label.

ratio is clamped to 0.0..=1.0. The returned Gauge auto-renders when dropped, so a bare ui.gauge(0.5); produces a default-width bar. Chain .label(...), .width(...), or .color(...) to customize. Call .show() (instead of dropping) to capture a GaugeResponse.

Color tiers follow theme colors: success below 50%, warning 50–80%, error at or above 80%. Override per-call with .color(...).

§Example
ui.gauge(0.6).label("60%");
let r = ui.gauge(0.42).label("CPU").width(48).show();
if r.hovered { /* attach tooltip */ }
§Family

The gauge family covers ratio-based progress indicators:

  • gauge — block-fill bar with a centered label (this method).
  • line_gauge — single-line bar with a trailing label and configurable fill/empty chars.
  • progress_bar / progress — unlabeled progress bars.
Source

pub fn line_gauge(&mut self, ratio: f64) -> LineGauge<'_>

Begin building a single-line gauge with configurable fill/empty chars.

ratio is clamped to 0.0..=1.0. Chain .label(...), .width(...), .filled(...), .empty(...) to customize. Auto-renders on Drop; call .show() to capture a GaugeResponse.

§Example
ui.line_gauge(0.6).label("60%").width(24);
ui.line_gauge(0.78).label("Memory").width(48).filled('━');
§Family

The gauge family covers ratio-based progress indicators:

Source§

impl Context

Source

pub fn scrollable_with_gutter<G, F>( &mut self, state: &mut ScrollState, opts: GutterOpts<G>, f: F, ) -> GutterResponse
where G: Fn(usize) -> String, F: FnMut(&mut Context, usize),

Scrollable column with a left gutter rendered per visible line.

state is the active scroll state. opts carries total_lines, viewport_height, and the gutter labeling closure (use GutterOpts::line_numbers for the common case). body_fn is invoked for each visible line and renders that line’s content. Highlighted lines (set via ScrollState::set_highlights) receive an accent background.

Returns a GutterResponse with the current highlight index and total highlight count for callers wiring up n / N search-result navigation keys.

§Example
let r = ui.scrollable_with_gutter(
    &mut scroll,
    GutterOpts::line_numbers(lines.len(), 10),
    |ui, abs_line| {
        if let Some(line) = lines.get(abs_line) {
            ui.text(*line);
        }
    },
);
if let Some(i) = r.current_highlight {
    // show "match i of N" status
}
Source§

impl Context

Source

pub fn separator(&mut self) -> Response

Render a horizontal divider line.

The line is drawn with the theme’s border color and expands to fill the container width.

Returns a Response so the divider’s hit-test rect is available for hover detection. Prior to v0.21.0 this returned &mut Self, but the chained style mutators (.bold(), .fg()) were a no-op — the cached separator string is already finalized — so the chain was dropped. Statement-form callers (ui.separator();) compile unchanged.

ui.separator();
Source

pub fn separator_colored(&mut self, color: Color) -> Response

Render a horizontal separator line with a custom color.

Returns a Response for hover detection; see Context::separator for the v0.21.0 return-shape change. Statement-form callers compile unchanged.

ui.separator_colored(Color::Cyan);
Source

pub fn screen( &mut self, name: &str, screens: &mut ScreenState, f: impl FnOnce(&mut Context), )

Conditionally render content when the named screen is active.

Each screen gets an isolated hook segment — use_state / use_memo calls inside one screen do not interfere with another screen’s hooks, even when you switch between screens across frames.

Focus state is saved and restored per screen automatically.

§Example
ui.screen("main", &mut screens, |ui| {
    ui.text("Main screen");
});
Source

pub fn col(&mut self, f: impl FnOnce(&mut Context)) -> Response

Create a vertical (column) container.

Children are stacked top-to-bottom. Returns a Response with click/hover state for the container area.

§Example
ui.col(|ui| {
    ui.text("line one");
    ui.text("line two");
});
Source

pub fn col_gap(&mut self, gap: u32, f: impl FnOnce(&mut Context)) -> Response

👎Deprecated since 0.20.1:

Use ui.container().gap(n).col(f) instead — same output, no name collision with ContainerBuilder::col_gap.

Create a vertical (column) container with a gap between children.

gap is the number of blank rows inserted between each child.

Deprecated since 0.20.1: the name collides with ContainerBuilder::col_gap, which sets the row-finalize main-axis gap (Tailwind gap-x axis convention) and so means the opposite thing. Use ui.container().gap(n).col(f) instead — same output, no collision.

Source

pub fn row(&mut self, f: impl FnOnce(&mut Context)) -> Response

Create a horizontal (row) container.

Children are placed left-to-right. Returns a Response with click/hover state for the container area.

§Example
ui.row(|ui| {
    ui.text("left");
    ui.spacer();
    ui.text("right");
});
Source

pub fn row_gap(&mut self, gap: u32, f: impl FnOnce(&mut Context)) -> Response

👎Deprecated since 0.20.1:

Use ui.container().gap(n).row(f) instead — same output, no name collision with ContainerBuilder::row_gap.

Create a horizontal (row) container with a gap between children.

gap is the number of blank columns inserted between each child.

Deprecated since 0.20.1: the name collides with ContainerBuilder::row_gap, which sets the column-finalize main-axis gap (Tailwind gap-y axis convention) and so means the opposite thing. Use ui.container().gap(n).row(f) instead — same output, no collision.

Source

pub fn line(&mut self, f: impl FnOnce(&mut Context)) -> &mut Self

Render inline text with mixed styles on a single line.

Unlike row, line() is designed for rich text — children are rendered as continuous inline text without gaps.

It intentionally returns &mut Self instead of Response so you can keep chaining display-oriented modifiers after composing the inline run.

§Example
ui.line(|ui| {
    ui.text("Status: ");
    ui.text("Online").bold().fg(Color::Green);
});
Source

pub fn line_wrap(&mut self, f: impl FnOnce(&mut Context)) -> &mut Self

Render inline text with mixed styles, wrapping at word boundaries.

Like line, but when the combined text exceeds the container width it wraps across multiple lines while preserving per-segment styles.

§Example
ui.line_wrap(|ui| {
    ui.text("This is a long ");
    ui.text("important").bold().fg(Color::Red);
    ui.text(" message that wraps across lines");
});
Source

pub fn modal(&mut self, f: impl FnOnce(&mut Context)) -> Response

Render content in a modal overlay with dimmed background.

if show {
    ui.modal(|ui| {
        ui.text("Are you sure?");
        if ui.button("OK").clicked { show = false; }
    });
}
Source

pub fn modal_with( &mut self, opts: ModalOptions, f: impl FnOnce(&mut Context), ) -> Response

Render content in a modal overlay with configurable options.

Like modal, but accepts a ModalOptions struct. Use this to opt into focus trapping (tab_trap: true) or future modal flags without breaking the bare modal() API.

When opts.tab_trap is true, focus cannot escape the modal’s focusable range — Tab/Shift+Tab keep cycling within the modal even if Context::set_focus_index or a mouse click moved focus to a background widget. WCAG 2.1 SC 2.4.3 (Focus Order) recommends trapping focus inside modal dialogs.

§Example
if show {
    ui.modal_with(slt::context::ModalOptions { tab_trap: true }, |ui| {
        ui.text("Are you sure?");
        if ui.button("OK").clicked { show = false; }
    });
}
Source

pub fn overlay(&mut self, f: impl FnOnce(&mut Context)) -> Response

Render floating content without dimming the background.

Source

pub fn overlay_at( &mut self, anchor: Anchor, f: impl FnOnce(&mut Context), ) -> Response

Render floating content anchored to one of the 9 compass positions.

Wraps overlay with a full-area column that pins the content to the requested anchor via flexbox align/justify. The inner column gets grow(1) so the wrapper consumes the screen, giving align/justify room to push the content to the corner.

ui.overlay_at(Anchor::TopRight, |ui| {
    ui.text("0:42").bold();
});
Source

pub fn modal_at( &mut self, anchor: Anchor, f: impl FnOnce(&mut Context), ) -> Response

Render a modal overlay anchored to one of the 9 compass positions.

Like modal but pinned to a corner / edge / center via the same anchor wrapping as overlay_at.

Source

pub fn overlay_at_offset( &mut self, anchor: Anchor, dx: i32, dy: i32, f: impl FnOnce(&mut Context), ) -> Response

Render f at anchor with cell offset (dx, dy) from the anchored edge.

This is the SLT analog of CSS position: absolute; top/right/bottom/left, or Flutter’s Positioned(top:, right:, ...). The 9-cell Anchor chooses which edge to anchor to; (dx, dy) insets toward the center.

§Sign convention

Positive dx / dy always inset toward the viewport center. So overlay_at_offset(Anchor::BottomRight, 2, 1, ...) places the widget 2 cells left and 1 cell up from the bottom-right corner.

For Anchor::Center (and other centered axes) negative values shift in the opposite direction — (dx=-2, dy=-1) shifts 2 cells left and 1 cell up. For corner / edge anchors, negative values would push the content off-screen, so they are clamped to 0; use a different anchor instead of negative offsets to escape an edge.

§CSS analogy
CSS:    place-self: end end; bottom: 1px; right: 2px;
SLT:    overlay_at_offset(Anchor::BottomRight, 2, 1, |ui| { ... })
§Example
// Inset corner badge — 2 cells from the right, 1 row from the bottom.
ui.overlay_at_offset(Anchor::BottomRight, 2, 1, |ui| {
    ui.text("v0.19.3").dim();
});
Source

pub fn modal_at_offset( &mut self, anchor: Anchor, dx: i32, dy: i32, f: impl FnOnce(&mut Context), ) -> Response

Modal variant of overlay_at_offset.

Like modal_at but with a (dx, dy) cell inset from the anchored edge. Positive values inset toward the center — see overlay_at_offset for the full sign convention.

§Example
ui.modal_at_offset(Anchor::TopRight, 2, 1, |ui| {
    ui.bordered(Border::Rounded).p(1).col(|ui| {
        ui.text("Saved!");
    });
});
Source

pub fn tooltip(&mut self, text: impl Into<String>)

Render a hover tooltip for the previously rendered interactive widget.

Call this right after a widget or container response:

if ui.button("Save").clicked { save(); }
ui.tooltip("Save the current document to disk");
Source

pub fn group(&mut self, name: &str) -> ContainerBuilder<'_>

Create a named group container for shared hover/focus styling.

ui.group("card").border(Border::Rounded)
    .group_hover_bg(Color::Indexed(238))
    .col(|ui| { ui.text("Hover anywhere"); });
Source

pub fn container(&mut self) -> ContainerBuilder<'_>

Create a container with a fluent builder.

Use this for borders, padding, grow, constraints, and titles. Chain configuration methods on the returned ContainerBuilder, then call .col() or .row() to finalize.

§Example
use slt::Border;
ui.container()
    .border(Border::Rounded)
    .p(1)
    .title("My Panel")
    .col(|ui| {
        ui.text("content");
    });
Source

pub fn scrollable(&mut self, state: &mut ScrollState) -> ContainerBuilder<'_>

Create a scrollable container. Handles wheel scroll and drag-to-scroll automatically.

Pass a ScrollState to persist scroll position across frames. The state is updated in-place with the current scroll offset and bounds.

§Example
let mut scroll = ScrollState::new();
ui.scrollable(&mut scroll).col(|ui| {
    for i in 0..100 {
        ui.text(format!("Line {i}"));
    }
});
Source

pub fn scroll_col( &mut self, state: &mut ScrollState, f: impl FnOnce(&mut Context), ) -> Response

Scrollable column container — shortcut for scrollable(state).grow(1).col(f).

This is the form used by nearly every scrollable view: a vertical list that fills its parent and wheels through its own content. Use the explicit Context::scrollable builder when you need custom grow, borders, padding, or a scrollbar alongside.

§Example
let mut scroll = ScrollState::new();
ui.scroll_col(&mut scroll, |ui| {
    for i in 0..100 {
        ui.text(format!("Line {i}"));
    }
});
Source

pub fn scroll_row( &mut self, state: &mut ScrollState, f: impl FnOnce(&mut Context), ) -> Response

Scrollable row container — shortcut for scrollable(state).grow(1).row(f).

Lays children out left-to-right and scrolls horizontally when their combined width exceeds the viewport: useful for timelines, kanban boards, wide tables, Gantt strips, and long single-line log entries (#247). The horizontal axis is driven by ScrollState::scroll_left / ScrollState::scroll_right, native horizontal mouse wheel, and shift+wheel. Nest a scroll_row inside a scroll_col to scroll both axes.

§Example
let mut scroll = ScrollState::new();
ui.scroll_row(&mut scroll, |ui| {
    for i in 0..40 {
        ui.text(format!("col-{i:02}  "));
    }
});
Source

pub fn scrollbar(&mut self, state: &mut ScrollState) -> Response

Render a scrollbar track for a ScrollState.

Displays a track () with a proportional thumb (). The thumb size and position are calculated from the scroll state’s content height, viewport height, and current offset.

Typically placed beside a scrollable() container in a row():

let mut scroll = ScrollState::new();
ui.row(|ui| {
    ui.scrollable(&mut scroll).grow(1).col(|ui| {
        for i in 0..100 { ui.text(format!("Line {i}")); }
    });
    ui.scrollbar(&mut scroll);
});
§Interaction (since 0.21.0)

The bar is a real input surface, mirroring split_pane’s drag handle:

  • Click-to-jump on the track: a left mouse-down inside the track but outside the thumb jumps state.offset so the clicked row maps proportionally to the content (top cell → offset 0, bottom cell → max_offset).
  • Drag-to-scroll on the thumb: a left mouse-down on the thumb sets ScrollState::dragging; subsequent drag events scroll proportionally to the cursor’s y within the track (even when the cursor leaves the track on the x-axis); mouse-up clears dragging.

Only the mouse events the bar acts on are consumed, so wheel scrolling over a sibling scrollable keeps working unchanged. Like every mouse handler the bar is inert while a modal is active and the bar is not inside it.

§Returns

A Response whose hit-test rect covers the scrollbar track — it is the track container’s own interaction response, so .clicked, .hovered, and .rect are populated for the track region. .changed is true on a frame where a scrollbar interaction moved the offset. When the content fits the viewport nothing is rendered and Response::none() is returned. Prior to v0.21.0 the receiver was &ScrollState; pass &mut scroll instead.

Source

pub fn bordered(&mut self, border: Border) -> ContainerBuilder<'_>

Shortcut for container().border(border).

Returns a ContainerBuilder pre-configured with the given border style.

Source

pub fn is_group_hovered(&self, name: &str) -> bool

Returns true if the named group is currently hovered by the mouse.

Uses the per-frame hovered_groups HashSet populated by Context::build_hovered_groups(); turns the previous O(n) scan over prev_group_rects into an O(1) lookup. Closes the cache half of #136 / #139.

Source

pub fn is_group_focused(&self, name: &str) -> bool

Returns true if the named group contains the currently focused widget.

Source

pub fn form( &mut self, state: &mut FormState, f: impl FnOnce(&mut Context, &mut FormState), ) -> &mut Self

Render a form that groups input fields vertically.

Wraps the fields in a column container and forwards the form state to the closure. Use Context::form_field inside the closure to render each field with label + input + error display.

Submission is driven by Context::form_submit. Per-field validators attached via FormField::validate run automatically inside Context::form_field; aggregate validity is read via FormState::is_valid.

Source

pub fn form_field(&mut self, field: &mut FormField) -> &mut Self

Render a single form field with label and input, running its validators.

The field’s own validators (attached via FormField::validate) run automatically according to its trigger: OnChange re-validates on each keystroke, OnBlur (the default) re-validates when focus leaves the field, and Manual never auto-validates. The resulting error is shown below the input.

With the async feature, any in-flight validate_async check is polled each frame and its result surfaced as the field error.

§Example
let mut field = FormField::new("Email")
    .validate(validators::email()); // OnBlur by default
ui.form_field(&mut field);
Source

pub fn form_submit(&mut self, label: impl Into<String>) -> Response

Render a primary-styled submit button.

Distinguishes the submit affordance from incidental buttons in the same form by rendering in the theme’s primary color (via ButtonVariant::Primary). Returns true in .clicked when the user clicks it, presses Enter while focused, or activates it with Space. Pair with FormState::validate_all / FormState::is_valid to gate submission on all fields being valid.

Source§

impl Context

Source

pub fn big_text(&mut self, s: impl Into<String>) -> Response

Render 8x8 bitmap text as half-block pixels (4 terminal rows tall).

Source

pub fn image(&mut self, img: &HalfBlockImage) -> Response

Render a half-block image in the terminal.

Each terminal cell displays two vertical pixels using the character with foreground (upper pixel) and background (lower pixel) colors.

Create a HalfBlockImage from a file (requires image feature):

let img = image::open("photo.png").unwrap();
let half = HalfBlockImage::from_dynamic(&img, 40, 20);
ui.image(&half);

Or from raw RGB data (no feature needed):

let rgb = vec![255u8; 30 * 20 * 3];
let half = HalfBlockImage::from_rgb(&rgb, 30, 10);
ui.image(&half);
Source

pub fn kitty_image( &mut self, rgba: &[u8], pixel_width: u32, pixel_height: u32, cols: u32, rows: u32, ) -> Response

Render a pixel-perfect image using the Kitty graphics protocol.

The image data must be raw RGBA bytes (4 bytes per pixel). The widget allocates cols x rows cells and renders the image at full pixel resolution within that space.

Requires a Kitty-compatible terminal (Kitty, Ghostty, WezTerm). On unsupported terminals, the area will be blank.

§Arguments
  • rgba - Raw RGBA pixel data
  • pixel_width - Image width in pixels
  • pixel_height - Image height in pixels
  • cols - Terminal cell columns to occupy
  • rows - Terminal cell rows to occupy
Source

pub fn kitty_image_fit( &mut self, rgba: &[u8], src_width: u32, src_height: u32, cols: u32, ) -> Response

Render a pixel-perfect image that preserves aspect ratio.

Sends the original RGBA data to the terminal and lets the Kitty protocol handle scaling. The container width is cols cells; height is calculated automatically from the image aspect ratio using detected cell pixel dimensions (falls back to 8×16 if detection fails).

Requires a Kitty-compatible terminal (Kitty, Ghostty, WezTerm).

Source

pub fn sixel_image( &mut self, rgba: &[u8], pixel_width: u32, pixel_height: u32, cols: u32, rows: u32, ) -> Response

Available on crate feature crossterm only.

Render an image using the Sixel protocol.

rgba is raw RGBA pixel data, pixel_width/pixel_height are pixel dimensions, and cols/rows are the terminal cell size to reserve for the image.

Requires the crossterm feature (enabled by default). Falls back to [sixel unsupported] on terminals without Sixel support. Set the SLT_FORCE_SIXEL=1 environment variable to skip terminal detection.

§Example
// 2x2 red square (RGBA: 4 pixels × 4 bytes)
let rgba = [255u8, 0, 0, 255].repeat(4);
ui.sixel_image(&rgba, 2, 2, 20, 2);
Source

pub fn iterm_image(&mut self, data: &[u8], cols: u32, rows: u32) -> Response

Available on crate feature crossterm only.

Render an image via iTerm2’s OSC 1337 inline-image protocol.

Unlike Context::kitty_image (raw RGBA) or Context::sixel_image (raw RGBA, quantized), data is encoded image-file bytes (PNG/JPEG/GIF): the terminal decodes and scales the file itself. This is the pixel-accurate path on Tabby, older iTerm2 builds, and WezTerm’s iTerm2-compat mode (issue #265).

cols/rows reserve the cell box for the image. On a terminal without OSC 1337 support the area is reserved and [iterm2 unsupported] is drawn, mirroring the Sixel fallback. Set SLT_FORCE_ITERM=1 to skip detection.

§Example
// `png` holds encoded PNG bytes loaded from disk or memory.
let png = [0x89u8, b'P', b'N', b'G'];
ui.iterm_image(&png, 20, 4);
Source

pub fn iterm_image_fit(&mut self, data: &[u8], cols: u32) -> Response

Available on crate feature crossterm only.

Render an iTerm2 OSC 1337 inline image preserving aspect ratio.

data is encoded image-file bytes (PNG/JPEG/GIF). The container is cols cells wide; height is reserved from the detected cell pixel dimensions (falling back to 8×16) and the OSC 1337 height=auto / preserveAspectRatio=1 flags let the terminal scale to fit. Mirrors Context::kitty_image_fit (issue #265).

Falls back to [iterm2 unsupported] on terminals without OSC 1337.

§Example
let png = [0x89u8, b'P', b'N', b'G'];
ui.iterm_image_fit(&png, 20);
Source

pub fn streaming_text(&mut self, state: &mut StreamingTextState) -> Response

Render streaming text with a typing cursor indicator.

Displays the accumulated text content. While streaming is true, shows a blinking cursor () at the end.

let mut stream = StreamingTextState::new();
stream.start();
stream.push("Hello from ");
stream.push("the AI!");
ui.streaming_text(&mut stream);
Source

pub fn streaming_markdown( &mut self, state: &mut StreamingMarkdownState, ) -> Response

Render streaming markdown with a typing cursor indicator.

Parses accumulated markdown content line-by-line while streaming. Supports headings, lists, inline formatting, horizontal rules, and fenced code blocks with open/close tracking across stream chunks.

let mut stream = StreamingMarkdownState::new();
stream.start();
stream.push("# Hello\n");
stream.push("- **streaming** markdown\n");
stream.push("```rust\nlet x = 1;\n");
ui.streaming_markdown(&mut stream);
Source

pub fn tool_approval(&mut self, state: &mut ToolApprovalState) -> Response

Render a tool approval widget with approve/reject buttons.

Shows the tool name, description, and two action buttons. Returns the updated ApprovalAction each frame.

let mut tool = ToolApprovalState::new("read_file", "Read contents of config.toml");
ui.tool_approval(&mut tool);
if tool.action == ApprovalAction::Approved {
}
Source

pub fn context_bar(&mut self, items: &[ContextItem]) -> Response

Render a context bar showing active context items with token counts.

Displays a horizontal bar of context sources (files, URLs, etc.) with their token counts, useful for AI chat interfaces.

let items = vec![ContextItem::new("main.rs", 1200), ContextItem::new("lib.rs", 800)];
ui.context_bar(&items);
Source§

impl Context

Source

pub fn split_pane<L, R>( &mut self, state: &mut SplitPaneState, left: L, right: R, ) -> SplitPaneResponse
where L: FnOnce(&mut Context), R: FnOnce(&mut Context),

Horizontal split container with a draggable handle.

Renders left | │ | right, where is a 1-cell wide drag handle. The handle is focusable; arrow keys (Left/Right) adjust the ratio by 5% per press, and dragging the handle with the mouse updates the ratio proportionally to the cursor’s x position.

§Example
ui.split_pane(
    &mut split,
    |ui| { ui.text("left pane"); },
    |ui| { ui.text("right pane"); },
);
Source

pub fn vsplit_pane<T, B>( &mut self, state: &mut SplitPaneState, top: T, bottom: B, ) -> SplitPaneResponse
where T: FnOnce(&mut Context), B: FnOnce(&mut Context),

Vertical split container with a draggable handle.

Mirrors Self::split_pane but stacks the panes vertically with a 1-row horizontal divider () between them. The handle is focusable; arrow keys (Up/Down) adjust the ratio by 5% per press.

§Example
ui.vsplit_pane(
    &mut split,
    |ui| { ui.text("top pane"); },
    |ui| { ui.text("bottom pane"); },
);
Source§

impl Context

Source

pub fn alert(&mut self, message: &str, level: AlertLevel) -> Response

Render an alert banner with icon and level-based coloring.

Argument order is (message, level) — message first, then the AlertLevel. This is the executable proof that API_DESIGN.md Rule 3 matches the shipped signature.

§Example
ui.alert("Disk full", AlertLevel::Error);
ui.alert("Saved", AlertLevel::Success);
Source

pub fn confirm(&mut self, question: &str, result: &mut bool) -> Response

Yes/No confirmation dialog. Returns Response with .clicked=true when answered.

result is set to true for Yes, false for No.

§Examples
let mut answer = false;
let r = ui.confirm("Delete this file?", &mut answer);
if r.clicked && answer { /* user confirmed */ }
Source

pub fn breadcrumb<'a>(&'a mut self, segments: &'a [&'a str]) -> Breadcrumb<'a>

Begin building a breadcrumb navigation bar with the default separator ().

Returns a Breadcrumb builder that auto-renders on Drop. Chain .separator(s) for a custom separator and .color(c) for a custom link color. Call .show() to render and obtain a BreadcrumbResponse carrying clicked_segment and Deref<Response>.

§Example
// simple
ui.breadcrumb(&["Home", "Settings", "Profile"]);

// with custom separator + color, capturing the response
let r = ui
    .breadcrumb(&["Home", "src", "lib.rs"])
    .separator(" > ")
    .show();
if let Some(i) = r.clicked_segment {
    // navigate to segment `i`
}
Source

pub fn accordion( &mut self, title: &str, open: &mut bool, f: impl FnOnce(&mut Context), ) -> Response

Collapsible section that toggles on click, Enter, or Space.

Source

pub fn definition_list(&mut self, items: &[(&str, &str)]) -> Response

Render a key-value definition list with aligned columns.

Keys are right-padded to the widest key so the value column lines up.

§Example
ui.definition_list(&[
    ("Name", "SuperLightTUI"),
    ("Version", "0.21.1"),
    ("License", "MIT"),
]);
Source

pub fn divider_text(&mut self, label: &str) -> Response

Render a horizontal divider with a centered text label.

The label is padded with one space on each side and centered between two separator runs spanning the available width.

§Example
ui.divider_text("Settings");
Source

pub fn badge(&mut self, label: &str) -> Response

Render a badge with the theme’s primary color.

Returns a Response carrying real hovered / right_clicked state for the badge’s rect, so callers can attach .on_hover(...) tooltips. Prior to v0.21.0 this always returned Response::none(); statement-form callers (ui.badge("NEW");) compile unchanged.

§Example
let r = ui.badge("NEW");
if r.hovered { /* attach a tooltip */ }
Source

pub fn badge_colored(&mut self, label: &str, color: Color) -> Response

Render a badge with a custom background color.

Foreground is auto-selected for contrast via Color::contrast_fg.

Returns a Response carrying real hovered / right_clicked state for the badge’s rect, so callers can attach .on_hover(...) tooltips. Prior to v0.21.0 this always returned Response::none(); statement-form callers compile unchanged.

§Example
let r = ui.badge_colored("ALPHA", Color::Magenta);
if r.hovered { /* attach a tooltip */ }
Source

pub fn key_hint(&mut self, key: &str) -> Response

Render a keyboard shortcut hint with reversed styling.

Returns a Response carrying real hovered / right_clicked state for the hint’s rect, so callers can attach .on_hover(...) tooltips. Prior to v0.21.0 this always returned Response::none(); statement-form callers compile unchanged.

§Example
ui.line(|ui| {
    ui.text("Quit: ");
    let r = ui.key_hint("Ctrl+Q");
    if r.hovered { /* attach a tooltip */ }
});
Source

pub fn stat(&mut self, label: &str, value: &str) -> Response

Render a label-value stat pair.

Renders as a column: a dim label above a bold value. Pair multiple stats in a row for a compact dashboard strip.

Returns a Response carrying real hovered / clicked / right_clicked state for the stat’s column rect, so callers can attach .on_hover(...) tooltips. Prior to v0.21.0 this always returned Response::none(); statement-form callers compile unchanged.

§Example
ui.row(|ui| {
    let r = ui.stat("Users", "1.2k");
    if r.hovered { /* attach a tooltip */ }
    ui.stat("Revenue", "$8,420");
});
Source

pub fn stat_colored( &mut self, label: &str, value: &str, color: Color, ) -> Response

Render a stat pair with a custom value color.

Returns a Response carrying real hovered / clicked / right_clicked state for the stat’s column rect, so callers can attach .on_hover(...) tooltips. Prior to v0.21.0 this always returned Response::none(); statement-form callers compile unchanged.

§Example
let r = ui.stat_colored("Errors", "0", Color::Green);
if r.hovered { /* attach a tooltip */ }
Source

pub fn stat_trend(&mut self, label: &str, value: &str, trend: Trend) -> Response

Render a stat pair with an up/down trend arrow.

The arrow color follows the theme: success for Trend::Up, error for Trend::Down.

Returns a Response carrying real hovered / clicked / right_clicked state for the stat’s column rect, so callers can attach .on_hover(...) tooltips. Prior to v0.21.0 this always returned Response::none(); statement-form callers compile unchanged.

§Example
let r = ui.stat_trend("MRR", "$24.5k", Trend::Up);
if r.hovered { /* attach a tooltip */ }
ui.stat_trend("Churn", "1.8%", Trend::Down);
Source

pub fn empty_state(&mut self, title: &str, description: &str) -> Response

Render a centered empty-state placeholder.

Title is rendered prominently; description is dimmed below. Both are centered horizontally and vertically inside the available space.

Returns a Response carrying real hovered / clicked / right_clicked state for the placeholder rect, so callers can attach .on_hover(...) tooltips. Prior to v0.21.0 this always returned Response::none(); statement-form callers compile unchanged.

§Example
if items.is_empty() {
    ui.empty_state("No items yet", "Press 'a' to add one");
}
Source

pub fn empty_state_action( &mut self, title: &str, description: &str, action_label: &str, ) -> Response

Render a centered empty-state placeholder with an action button.

Returns a Response whose clicked field is true on the frame the action button is activated. As of v0.21.0 the response also carries real hovered / right_clicked state (and the laid-out rect) for the placeholder area, so callers can attach .on_hover(...) tooltips. The clicked / changed fields still track the action button specifically, not the whole placeholder.

§Example
if items.is_empty() {
    let r = ui.empty_state_action("No items yet", "Get started", "Add first item");
    if r.clicked {
        // open create flow
    }
}
Source

pub fn code_block<'a>(&'a mut self, code: &'a str) -> CodeBlock<'a>

Begin building a syntax-highlighted code block.

Chain .lang(...) for language-aware highlighting and .numbered() for a line-number gutter. The returned CodeBlock auto-renders when dropped, so a bare ui.code_block(code); produces a default block. Call .show() (instead of dropping) to capture the Response.

This is the consuming-builder shape shared with Context::gauge / Context::breadcrumb — see API_DESIGN.md Rule 1.

§Example
ui.code_block("let x = 1;");
let r = ui.code_block("fn main() {}").lang("rust").numbered().show();
if r.hovered { /* attach tooltip */ }
Source

pub fn code_block_lang(&mut self, code: &str, lang: &str) -> Response

👎Deprecated since 0.21.0:

use code_block(code).lang(lang)

Render a code block with language-aware syntax highlighting.

Source

pub fn code_block_numbered(&mut self, code: &str) -> Response

👎Deprecated since 0.21.0:

use code_block(code).numbered()

Render a code block with line numbers and keyword highlighting.

Source

pub fn code_block_numbered_lang(&mut self, code: &str, lang: &str) -> Response

👎Deprecated since 0.21.0:

use code_block(code).lang(lang).numbered()

Render a code block with line numbers and language-aware highlighting.

Source§

impl Context

Source

pub fn text(&mut self, s: impl Into<String>) -> &mut Self

Render a text element. Returns &mut Self for style chaining.

§Example
use slt::Color;
ui.text("hello").bold().fg(Color::Cyan);

Render a clickable hyperlink.

The link is interactive: clicking it (or pressing Enter/Space when focused) opens the URL in the system browser. OSC 8 is also emitted for terminals that support native hyperlinks.

Source

pub fn timer_display(&mut self, elapsed: Duration) -> &mut Self

Render an elapsed time display.

Formats as HH:MM:SS.CC when hours are non-zero, otherwise MM:SS.CC.

Source

pub fn help_from_keymap(&mut self, keymap: &KeyMap) -> Response

Render help bar from a KeyMap. Shows visible bindings as key-description pairs.

Source

pub fn bold(&mut self) -> &mut Self

Apply bold to the last rendered text element.

Source

pub fn dim(&mut self) -> &mut Self

Apply dim styling to the last rendered text element.

Also sets the foreground color to the theme’s text_dim color if no explicit foreground has been set.

Source

pub fn italic(&mut self) -> &mut Self

Apply italic to the last rendered text element.

Source

pub fn underline(&mut self) -> &mut Self

Apply underline to the last rendered text element.

Source

pub fn reversed(&mut self) -> &mut Self

Apply reverse-video to the last rendered text element.

Source

pub fn strikethrough(&mut self) -> &mut Self

Apply strikethrough to the last rendered text element.

Source

pub fn fg(&mut self, color: Color) -> &mut Self

Set the foreground color of the last rendered text element.

Source

pub fn bg(&mut self, color: Color) -> &mut Self

Set the background color of the last rendered text element.

Source

pub fn gradient(&mut self, from: Color, to: Color) -> &mut Self

Apply a per-character foreground gradient to the last rendered text.

Source

pub fn gradient_stops(&mut self, stops: &[(f32, Color)]) -> &mut Self

Apply a per-character multi-stop foreground gradient to the last text.

stops is a slice of (position, color) pairs where position lies in 0.0..=1.0. Stops do not need to be pre-sorted. The text is colored by linearly interpolating between adjacent stops across its displayed columns, using the same column-mapping and clamping as gradient.

  • An empty slice is a no-op (the text keeps its current style).
  • A single stop produces a solid color.
§Example
use slt::Color;
ui.text("rainbow").gradient_stops(&[
    (0.0, Color::Red),
    (0.5, Color::Yellow),
    (1.0, Color::Green),
]);
Source

pub fn bg_gradient(&mut self, from: Color, to: Color) -> &mut Self

Apply a per-character background gradient to the last rendered text.

The two-stop background analogue of gradient. Colors the cell background instead of the foreground, using identical column-mapping and clamping so width handling stays consistent.

§Example
use slt::Color;
ui.text("banner").bg_gradient(Color::Blue, Color::Magenta);
Source

pub fn bg_gradient_stops(&mut self, stops: &[(f32, Color)]) -> &mut Self

Apply a per-character multi-stop background gradient to the last text.

The background analogue of gradient_stops: identical stop handling (positions in 0.0..=1.0, unsorted-safe, empty = no-op, single stop = solid) but applied to the cell background instead of the foreground.

§Example
use slt::Color;
ui.text("header").bg_gradient_stops(&[
    (0.0, Color::Blue),
    (1.0, Color::Magenta),
]);
Source

pub fn group_hover_fg(&mut self, color: Color) -> &mut Self

Set foreground color when the current group is hovered or focused.

Source

pub fn group_hover_bg(&mut self, color: Color) -> &mut Self

Set background color when the current group is hovered or focused.

Source

pub fn styled(&mut self, s: impl Into<String>, style: Style) -> &mut Self

Render a text element with an explicit Style applied immediately.

Equivalent to calling text(s) followed by style-chain methods, but more concise when you already have a Style value.

Source

pub fn wrap(&mut self) -> &mut Self

Enable word-boundary wrapping on the last rendered text element.

Source

pub fn truncate(&mut self) -> &mut Self

Truncate the last rendered text with when it exceeds its allocated width. Use with .w() to set a fixed width, or let the parent container constrain it.

Source

pub fn grow(&mut self, value: u16) -> &mut Self

Set the flex-grow factor of the last rendered text element.

A value of 1 causes the element to expand and fill remaining space along the main axis.

Source

pub fn align(&mut self, align: Align) -> &mut Self

Set the text alignment of the last rendered text element.

Source

pub fn text_center(&mut self) -> &mut Self

Center-align the last rendered text element horizontally. Shorthand for .align(Align::Center). Requires the text to have a width constraint (via .w() or parent container) to be visible.

Source

pub fn text_right(&mut self) -> &mut Self

Right-align the last rendered text element horizontally. Shorthand for .align(Align::End).

Source

pub fn w(&mut self, value: u32) -> &mut Self

Set a fixed width on the last rendered text or link element.

Sets the WidthSpec to Fixed(value), making the element occupy exactly that many columns (padded with spaces or truncated).

Source

pub fn h(&mut self, value: u32) -> &mut Self

Set a fixed height on the last rendered text or link element.

Sets the HeightSpec to Fixed(value).

Source

pub fn min_w(&mut self, value: u32) -> &mut Self

Set the minimum width on the last rendered text or link element.

Source

pub fn max_w(&mut self, value: u32) -> &mut Self

Set the maximum width on the last rendered text or link element.

Source

pub fn min_h(&mut self, value: u32) -> &mut Self

Set the minimum height on the last rendered text or link element.

Source

pub fn max_h(&mut self, value: u32) -> &mut Self

Set the maximum height on the last rendered text or link element.

Source

pub fn m(&mut self, value: u32) -> &mut Self

Set uniform margin on all sides of the last rendered text or link element.

Source

pub fn mx(&mut self, value: u32) -> &mut Self

Set horizontal margin (left + right) on the last rendered text or link.

Source

pub fn my(&mut self, value: u32) -> &mut Self

Set vertical margin (top + bottom) on the last rendered text or link.

Source

pub fn mt(&mut self, value: u32) -> &mut Self

Set top margin on the last rendered text or link element.

Source

pub fn mr(&mut self, value: u32) -> &mut Self

Set right margin on the last rendered text or link element.

Source

pub fn mb(&mut self, value: u32) -> &mut Self

Set bottom margin on the last rendered text or link element.

Source

pub fn ml(&mut self, value: u32) -> &mut Self

Set left margin on the last rendered text or link element.

Source

pub fn spacer(&mut self) -> &mut Self

Render an invisible spacer that expands to fill available space.

Useful for pushing siblings to opposite ends of a row or column.

Source

pub fn with_if(&mut self, cond: bool, f: impl FnOnce(&mut Self)) -> &mut Self

Apply f only if cond is true. Returns self so chaining continues.

Use this to attach a block of style modifiers to the last rendered text without breaking the fluent chain. The closure receives the same &mut Context, so any style-chain method (.bold(), .fg(), etc.) applies to the most recent text element.

Zero allocation: the closure is inlined and skipped entirely when cond is false.

§Example
use slt::Color;
let is_error = true;
let is_selected = false;
ui.text("Status")
    .with_if(is_error, |t| {
        t.bold().fg(Color::Red);
    })
    .with_if(is_selected, |t| {
        t.bg(Color::DarkGray);
    });
Source

pub fn with(&mut self, f: impl FnOnce(&mut Self)) -> &mut Self

Apply f unconditionally. Useful for factoring out a block of modifier calls that should always run, while keeping the fluent chain intact.

§Example
use slt::Color;
ui.text("hi").with(|t| {
    t.bold().fg(Color::Cyan);
});
Source§

impl Context

Source

pub fn spinner(&mut self, state: &SpinnerState) -> Response

Render an animated spinner.

The spinner advances one frame per tick. Use SpinnerState::dots or SpinnerState::line to create the state.

Returns a Response with hovered populated correctly so callers can attach tooltips or react to mouse interaction. Prior to v0.20.0 this returned &mut Self; existing code that ignores the return value keeps compiling, though the #[must_use] attribute on Response surfaces a warning that nudges callers to handle interaction state.

Source

pub fn toast(&mut self, state: &mut ToastState) -> &mut Self

Render toast notifications. Calls state.cleanup(tick) automatically.

Expired messages are removed before rendering. If there are no active messages, nothing is rendered and self is returned unchanged.

Source

pub fn slider( &mut self, label: &str, value: &mut f64, range: RangeInclusive<f64>, ) -> Response

Horizontal slider for numeric values.

Step defaults to span / 20.0. Use Context::slider_with_step for an explicit step (e.g. integer volume controls).

§Examples
let mut volume = 75.0_f64;
let r = ui.slider("Volume", &mut volume, 0.0..=100.0);
if r.changed { /* volume was adjusted */ }
Source

pub fn slider_with_step( &mut self, label: &str, value: &mut f64, range: RangeInclusive<f64>, step: f64, ) -> Response

Horizontal slider with an explicit step size.

Each Left/Right (or h/l) advances value by step. Use this when the default step (span / 20) is too coarse or too fine — for example integer counters need step = 1.0, fine controls need step = 0.1.

§Examples
let mut volume = 50.0_f64;
ui.slider_with_step("Volume", &mut volume, 0.0..=100.0, 1.0);
Source

pub fn number_input(&mut self, state: &mut NumberInputState) -> Response

Numeric stepper field: Up/Down (or k/j) and scroll-wheel adjust by step, or type a value directly and press Enter. The committed value is always clamped to [min, max] (and rounded in integer mode).

Unlike slider — a bar-and-thumb control keyed by Left/Right — this renders the raw value as a ▾ 42 ▴ field that accepts direct typing. Config lives on NumberInputState. Up/k increments, Down/j decrements; Enter commits a typed buffer, Esc discards it, Backspace edits it. Left/Right are intentionally unused (reserved).

Response.focused reflects focus and Response.changed is true iff the committed value changed this frame. All handled key and scroll events are consumed so they do not leak to other widgets or the global quit handler.

Available since 0.21.0.

§Example
let mut qty = NumberInputState::integer(3, 0, 10).step(1.0);
let r = ui.number_input(&mut qty);
if r.changed { /* qty.value updated */ }
Source§

impl Context

Source

pub fn text_input(&mut self, state: &mut TextInputState) -> Response

Render a single-line text input. Auto-handles cursor, typing, and backspace.

The widget claims focus via Context::register_focusable. When focused, it consumes character, backspace, arrow, Home, and End key events.

§Example
let mut input = TextInputState::with_placeholder("Search...");
ui.text_input(&mut input);
// input.value holds the current text
Source

pub fn text_input_colored( &mut self, state: &mut TextInputState, colors: &WidgetColors, ) -> Response

Render a text input with custom widget colors.

Source§

impl Context

Source

pub fn textarea( &mut self, state: &mut TextareaState, visible_rows: u32, ) -> Response

When focused, handles character input, Enter (new line), Backspace, arrow keys, Home, and End. The cursor is rendered as a block character.

Set TextareaState::word_wrap to enable soft-wrapping at a given display-column width. Up/Down then navigate visual lines.

Editing shortcuts: Ctrl+K deletes from the cursor to the end of the current line. Ctrl+Left / Alt+Left jumps to the previous word boundary; Ctrl+Right / Alt+Right jumps past the next word end. Ctrl+Z undoes the last edit and Ctrl+Y redoes it — see the TextareaState docs for the snapshot policy.

Source

pub fn progress(&mut self, ratio: f64) -> Response

Render a progress bar (20 chars wide). ratio is clamped to 0.0..=1.0.

Uses block characters ( filled, empty). For a custom width use Context::progress_bar. For an inline label use Context::gauge.

Returns a Response so callers can detect hover, attach a tooltip, or implement click-to-set scrubbers. Prior to v0.20.0 this returned &mut Self; ignoring the return value still compiles but the #[must_use] attribute on Response warns at the call site.

Source

pub fn progress_bar(&mut self, ratio: f64, width: u32) -> Response

Render a progress bar with a custom character width.

ratio is clamped to 0.0..=1.0. width is the total number of characters rendered.

Source

pub fn progress_bar_colored( &mut self, ratio: f64, width: u32, color: Color, ) -> Response

Render a progress bar with a custom fill color.

Source§

impl Context

Source

pub fn grid(&mut self, cols: u32, f: impl FnOnce(&mut Context)) -> Response

Render children in a fixed grid with the given number of columns.

Children are placed left-to-right, top-to-bottom. Each cell has equal width (area_width / cols). Rows wrap automatically.

§Example
ui.grid(3, |ui| {
    for i in 0..9 {
        ui.text(format!("Cell {i}"));
    }
});
Source

pub fn grid_with( &mut self, columns: &[GridColumn], f: impl FnOnce(&mut Context), ) -> Response

Render children in a grid with per-column width specifications.

The number of columns is determined by the length of columns. Children are placed left-to-right, top-to-bottom, wrapping into rows automatically.

§Column specifications
§Example
use slt::GridColumn;
ui.grid_with(&[
    GridColumn::Fixed(8),
    GridColumn::Grow(1),
    GridColumn::Grow(1),
    GridColumn::Fixed(4),
], |ui| {
    for i in 0..8 {
        ui.text(format!("Cell {i}"));
    }
});
Source

pub fn list(&mut self, state: &mut ListState) -> Response

Render a selectable list. Handles Up/Down (and k/j) navigation when focused.

The selected item is highlighted with the theme’s primary color. If the list is empty, nothing is rendered.

Source

pub fn list_colored( &mut self, state: &mut ListState, colors: &WidgetColors, ) -> Response

Render a navigable list with custom widget colors.

Source

pub fn list_reorderable(&mut self, state: &mut ListState) -> ListResponse

Render a selectable list that supports keyboard reordering of items.

Behaves exactly like list for navigation (Up/Down and k/j move the selection) and click selection, but additionally lets the focused user reorder the selected item with Shift+Up/Shift+Down or Alt+Up/Alt+Down. Reordering operates on the underlying item order via ListState::move_item, keeping the selection on the moved item.

Returns a ListResponse which derefs to the standard Response and exposes reorderedSome((from, to)) with the data indices when an item moved this frame, otherwise None.

The plain list entry point is unchanged; opt into reordering by calling this method instead.

§Example
let r = ui.list_reorderable(&mut list);
if let Some((from, to)) = r.reordered {
    let _ = (from, to); // persist new order
}

Available since 0.21.1.

Source

pub fn list_reorderable_colored( &mut self, state: &mut ListState, colors: &WidgetColors, ) -> ListResponse

Render a reorderable list with custom widget colors.

See list_reorderable for the reorder keybindings and return semantics.

Available since 0.21.1.

Source

pub fn calendar(&mut self, state: &mut CalendarState) -> Response

Render a calendar date picker with month navigation.

Single-date mode is the default. Opt into range selection with CalendarState::with_range and an optional HH:MM time row with CalendarState::with_time.

§Keybindings (when focused)
KeyAction
Left / hPrevious day
Right / lNext day
UpPrevious week (−7 days)
DownNext week (+7 days)
[Previous month
]Next month
Enter / SpaceSelect cursor day (range: set anchor)
Shift+Left / Shift+HExtend range −1 day
Shift+Right / Shift+LExtend range +1 day
Shift+UpExtend range −7 days
Shift+DownExtend range +7 days
Shift+Enter / Shift+SpaceSet range extent at cursor

h/l follow vim convention (cursor by one day). Use [/] for month navigation. Mouse clicks on the title row navigate months and clicks inside the day grid select that day; in range mode a Shift+left-click sets the range extent endpoint.

§Example
cal.with_range();
let resp = ui.calendar(&mut cal);
if resp.changed {
    if let Some((start, end)) = cal.selected_range() {
        ui.text(format!("{}-{:02}-{:02} → {}-{:02}-{:02}",
            start.year, start.month, start.day,
            end.year, end.month, end.day));
    }
}
Source

pub fn file_picker(&mut self, state: &mut FilePickerState) -> Response

Render a file system browser with directory navigation.

Source§

impl Context

Source

pub fn help(&mut self, bindings: &[(&str, &str)]) -> Response

Render a help bar showing keybinding hints.

bindings is a slice of (key, action) pairs. Keys are rendered in the theme’s primary color; actions in the dim text color. Pairs are separated by a · character.

Source

pub fn help_colored( &mut self, bindings: &[(&str, &str)], key_color: Color, text_color: Color, ) -> Response

Render a help bar with custom key/description colors.

Source

pub fn key(&self, c: char) -> bool

Check if a character key was pressed this frame.

Returns true if the key event has not been consumed by another widget.

Source

pub fn key_code(&self, code: KeyCode) -> bool

Check if a specific key code was pressed this frame.

Returns true if the key event has not been consumed by another widget. Blocked when a modal/overlay is active and the caller is outside the overlay. Use raw_key_code for global shortcuts that must work regardless of modal/overlay state.

Source

pub fn raw_key_code(&self, code: KeyCode) -> bool

Check if a specific key code was pressed this frame, ignoring modal/overlay state.

Unlike key_code, this method bypasses the modal/overlay guard so it works even when a modal or overlay is active. Use this for global shortcuts (e.g. Esc to close a modal, Ctrl+Q to quit) that must always be reachable.

Returns true if the key event has not been consumed by another widget.

Source

pub fn key_release(&self, c: char) -> bool

Check if a character key was released this frame.

Returns true if the key release event has not been consumed by another widget.

Source

pub fn key_code_release(&self, code: KeyCode) -> bool

Check if a specific key code was released this frame.

Returns true if the key release event has not been consumed by another widget.

Source

pub fn consume_key(&mut self, c: char) -> bool

Check for a character key press and consume the event, preventing other handlers from seeing it.

Returns true if the key was found unconsumed and is now consumed. Unlike key() which peeks without consuming, this claims exclusive ownership of the event.

Call after widgets if you want widgets to have priority over your handler, or before widgets to intercept first.

Source

pub fn consume_key_code(&mut self, code: KeyCode) -> bool

Check for a special key press and consume the event, preventing other handlers from seeing it.

Returns true if the key was found unconsumed and is now consumed. Unlike key_code() which peeks without consuming, this claims exclusive ownership of the event.

Call after widgets if you want widgets to have priority over your handler, or before widgets to intercept first.

Source

pub fn key_mod(&self, c: char, modifiers: KeyModifiers) -> bool

Check if a character key with specific modifiers was pressed this frame.

Returns true if the key event has not been consumed by another widget.

Source

pub fn raw_key_mod(&self, c: char, modifiers: KeyModifiers) -> bool

Like key_mod but bypasses the modal/overlay guard.

Source

pub fn mouse_down(&self) -> Option<(u32, u32)>

Return the position of a left mouse button down event this frame, if any.

Returns None if no unconsumed mouse-down event occurred.

Source

pub fn mouse_drag(&self) -> Option<(u32, u32)>

Return the position of a left mouse button drag event this frame, if any.

Returns None if no unconsumed drag event occurred. Drag events fire while the left button is held and the cursor moves.

Source

pub fn mouse_up(&self) -> Option<(u32, u32)>

Return the position of a left mouse button release event this frame, if any.

Returns None if no unconsumed mouse-up event occurred.

Source

pub fn mouse_down_button(&self, button: MouseButton) -> Option<(u32, u32)>

Return the position of a mouse button down event for the specified button.

This is a generalized version of mouse_down that accepts any MouseButton.

Source

pub fn mouse_drag_button(&self, button: MouseButton) -> Option<(u32, u32)>

Return the position of a mouse drag event for the specified button.

Source

pub fn mouse_up_button(&self, button: MouseButton) -> Option<(u32, u32)>

Return the position of a mouse button release event for the specified button.

Source

pub fn mouse_pos(&self) -> Option<(u32, u32)>

Return the current mouse cursor position, if known.

The position is updated on every mouse move or click event. Returns None until the first mouse event is received.

Source

pub fn paste(&self) -> Option<&str>

Return the first unconsumed paste event text, if any.

Source

pub fn scroll_up(&self) -> bool

Check if an unconsumed scroll-up event occurred this frame.

Source

pub fn scroll_down(&self) -> bool

Check if an unconsumed scroll-down event occurred this frame.

Source

pub fn scroll_left(&self) -> bool

Check if an unconsumed scroll-left event occurred this frame.

Source

pub fn scroll_right(&self) -> bool

Check if an unconsumed scroll-right event occurred this frame.

Source

pub fn events(&self) -> impl Iterator<Item = &Event>

Iterate over unconsumed events this frame, respecting the modal guard.

Returns an empty iterator when a modal is active and the caller is not inside an overlay. Use raw_events to bypass the modal guard (e.g., for global hotkeys).

§Example
for event in ui.events() {
    if let slt::Event::Mouse(mouse) = event {
        if matches!(mouse.kind, slt::MouseKind::Down(slt::MouseButton::Right)) {
            // handle right-click
        }
    }
}
Source

pub fn raw_events(&self) -> impl Iterator<Item = &Event> + '_

Iterate over all unconsumed events, bypassing the modal guard.

Use this for global shortcuts that must work even when a modal or overlay is active. Prefer events for normal use.

Source

pub fn quit(&mut self)

Signal the run loop to exit after this frame.

Source

pub fn copy_to_clipboard(&mut self, text: impl Into<String>)

Copy text to the system clipboard via OSC 52.

Works transparently over SSH connections. The text is queued and written to the terminal after the current frame renders.

Requires a terminal that supports OSC 52 (most modern terminals: Ghostty, kitty, WezTerm, iTerm2, Windows Terminal).

Source

pub fn theme(&self) -> &Theme

Get the current theme.

Source

pub fn color(&self, token: ThemeColor) -> Color

Resolve a ThemeColor token against the current theme.

Source

pub fn spacing(&self) -> Spacing

Get the current spacing scale from the theme.

Source

pub fn set_theme(&mut self, theme: Theme)

Change the theme for subsequent rendering.

All widgets rendered after this call will use the new theme’s colors.

Source

pub fn is_dark_mode(&self) -> bool

Check if dark mode is active.

Source

pub fn set_dark_mode(&mut self, dark: bool)

Set dark mode. When true, dark_* style variants are applied.

Source

pub fn width(&self) -> u32

Get the terminal width in cells.

Source

pub fn breakpoint(&self) -> Breakpoint

Get the current terminal width breakpoint.

Returns a Breakpoint based on the terminal width:

  • Xs: < 40 columns
  • Sm: 40-79 columns
  • Md: 80-119 columns
  • Lg: 120-159 columns
  • Xl: >= 160 columns

Use this for responsive layouts that adapt to terminal size:

match ui.breakpoint() {
    Breakpoint::Xs | Breakpoint::Sm => {
        ui.col(|ui| { ui.text("Stacked layout"); });
    }
    _ => {
        ui.row(|ui| { ui.text("Side-by-side layout"); });
    }
}
Source

pub fn height(&self) -> u32

Get the terminal height in cells.

Source

pub fn tick(&self) -> u64

Get the current tick count (increments each frame).

Useful for animations and time-based logic. The tick starts at 0 and increases by 1 on every rendered frame.

Source

pub fn debug_enabled(&self) -> bool

Return whether the layout debugger is enabled.

The debugger is toggled with F12 at runtime.

Source

pub fn debug_layer(&self) -> DebugLayer

Return which layers the F12 debug overlay outlines (issue #201).

Default is crate::DebugLayer::All, which outlines the base tree plus any active overlays/modals. See set_debug_layer to narrow the outline to a specific layer.

§Example
use slt::{Context, DebugLayer};

slt::run(|ui: &mut Context| {
    // Read the current layer to drive a UI badge or debug toolbar.
    match ui.debug_layer() {
        DebugLayer::All => ui.text("layer: all"),
        DebugLayer::TopMost => ui.text("layer: topmost"),
        DebugLayer::BaseOnly => ui.text("layer: base"),
    };
}).unwrap();
Source

pub fn set_debug_layer(&mut self, layer: DebugLayer)

Choose which layers the F12 debug overlay outlines (issue #201).

Persists across frames. The default (crate::DebugLayer::All) matches the reporter’s expectation that F12 reflects everything the renderer is drawing. Use crate::DebugLayer::TopMost to focus on the active modal / overlay only, or crate::DebugLayer::BaseOnly to keep the legacy behavior of skipping overlays.

§Runtime keybinding

At runtime, Shift+F12 cycles through AllTopMostBaseOnlyAll. Plain F12 still toggles the overlay on/off. The two keys are independent: enabling the overlay does not change the active layer, and cycling layers does not enable the overlay.

§Example
use slt::{Context, DebugLayer};

slt::run(|ui: &mut Context| {
    // Toggle between viewing only the base tree and viewing all
    // layers, e.g. from a custom debug menu.
    let next = match ui.debug_layer() {
        DebugLayer::All => DebugLayer::BaseOnly,
        DebugLayer::BaseOnly => DebugLayer::TopMost,
        DebugLayer::TopMost => DebugLayer::All,
    };
    ui.set_debug_layer(next);
}).unwrap();
Source

pub fn inspector(&self) -> bool

Return whether the devtools inspector panel is active (issue #268).

The inspector is toggled with Ctrl+F12 at runtime, or programmatically via set_inspector. It is independent of the F12 outline overlay and the Shift+F12 layer cycle. When on, the inspector draws a resolved-style panel for the focused widget and a focus-chain panel listing every focusable in order.

Since 0.21.0.

§Example
use slt::Context;

slt::run(|ui: &mut Context| {
    if ui.inspector() {
        ui.text("inspector on (Ctrl+F12 to hide)");
    }
})
.unwrap();
Source

pub fn set_inspector(&mut self, on: bool)

Show or hide the devtools inspector panel (issue #268).

Symmetric with set_debug_layer: the change persists across frames. Enables (or disables) the focused-widget resolved-style panel and the focus-chain inspector. Equivalent to the runtime Ctrl+F12 toggle; does not affect the F12 outline overlay.

Since 0.21.0.

§Example
use slt::Context;

slt::run(|ui: &mut Context| {
    // Open the inspector from a custom debug menu.
    ui.set_inspector(true);
})
.unwrap();
Source§

impl Context

Source

pub fn rich_log(&mut self, state: &mut RichLogState) -> Response

Render a scrollable rich log view with styled entries.

Source

pub fn virtual_list( &mut self, state: &mut ListState, visible_height: u32, f: impl Fn(&mut Context, usize), ) -> Response

Render a virtual list that only renders visible items.

total is the number of items. visible_height limits how many rows are rendered. The closure f is called only for visible indices.

This is the uniform fixed-height fast path: every item is treated as exactly one row. For chat/feed bubbles of differing heights see virtual_list_variable.

Source

pub fn virtual_list_variable( &mut self, state: &mut ListState, visible_height: u32, f: impl Fn(&mut Context, usize), ) -> Response

Variable-height variant of virtual_list.

Each item’s height (in rows) comes from ListState::set_item_heights; the visible range is computed so the rendered items fill at most visible_height rows starting from the current viewport. This is the chat/feed use case where bubbles vary in height (a one-line reply next to a 30-line code block). When no per-item heights are set it falls back to the uniform fast path and produces output identical to virtual_list. Rendering remains O(visible): only items in the computed range invoke f, prefix-sum lookups are O(log n) and the prefix-sum rebuild is O(n) gated behind a dirty flag.

An item taller than visible_height renders from its top and is never skipped. PageUp/PageDown move the selection by the number of items that fill visible_height rows from the current position. The “↑ N more / ↓ N more” affordances continue to count items.

§Example
use slt::widgets::ListState;

let mut state = ListState::new(vec!["short reply", "long\ncode\nblock", "ok"])
    .with_item_heights(vec![1, 3, 1]);

slt::run(|ui| {
    ui.virtual_list_variable(&mut state, 10, |ui, idx| {
        ui.text(format!("bubble {idx}"));
    });
})?;

Available since 0.21.0.

Source

pub fn command_palette(&mut self, state: &mut CommandPaletteState) -> Response

Render a command palette overlay.

Source

pub fn markdown(&mut self, text: &str) -> Response

Render a markdown string with basic formatting.

Supports headers (#), bold (**), italic (*), inline code (`), unordered lists (-/*), ordered lists (1.), blockquotes (>), horizontal rules (---), links ([text](url)), image placeholders (![alt](url)), code blocks with syntax highlighting, and GFM-style pipe tables. Paragraph text auto-wraps to container width.

Source

pub fn key_chord(&mut self, seq: &str) -> bool

Match a multi-key sequence whose keystrokes may span multiple frames (vi gg, leader keys).

Unlike a single-frame matcher, key_chord buffers partial input in crate-internal FrameState across frames: typing g on one frame and g on the next returns true on the second frame. The partial prefix is cleared on a non-matching key press (vi semantics: g then x cancels a pending gg) or after DEFAULT_CHORD_TIMEOUT_TICKS of inactivity (measured on the same tick clock as notifications/animation).

Returns true exactly once, on the frame that completes the sequence; the completing key event is consumed so downstream widgets in the same frame do not also handle it. It does not re-fire on later frames without new input.

§Leader notation

A leading <space> or <leader> token (or a literal space) matches the space key, e.g. key_chord("<space>ff"), key_chord("<leader>ff"), and key_chord(" ff") are equivalent. Only <space> / <leader> are recognized as special tokens; every other character is matched literally. Modifier-aware chords (C-x C-s) are out of scope.

An empty sequence always returns false.

§Example
slt::run(|ui: &mut slt::Context| {
    if ui.key_chord("gg") {
        // vi-style: jump to the top
    }
    if ui.key_chord("<space>ff") {
        // leader key: open a file finder
    }
});
Source

pub fn key_chord_timeout(&mut self, seq: &str, timeout_ticks: u64) -> bool

key_chord with an explicit per-call timeout in ticks.

A partial sequence is abandoned if timeout_ticks elapse on the tick clock without a matching next key. Use this when a chord should be more forgiving (large value) or stricter (small value) than the DEFAULT_CHORD_TIMEOUT_TICKS default. All other behavior matches key_chord.

§Example
slt::run(|ui: &mut slt::Context| {
    // Require the second `g` within ~0.25s at 60Hz.
    if ui.key_chord_timeout("gg", 15) {
        // jump to top
    }
});
Source

pub fn key_seq(&mut self, seq: &str) -> bool

👎Deprecated since 0.21.0:

renamed to key_chord; now matches across frames

Check if a sequence of character keys was pressed.

Deprecated alias for key_chord. The original key_seq only matched when every key arrived in a single poll batch (i.e. physically simultaneous keypresses), so vi gg / leader keys were unreachable at any human typing speed. It now delegates to key_chord and matches across frames.

Source§

impl Context

Source

pub fn table(&mut self, state: &mut TableState) -> Response

Render a data table with sortable columns and row selection.

Handles Up/Down selection when focused. Column widths are computed automatically from header and cell content. The selected row is highlighted with the theme’s selection colors.

Source

pub fn table_colored( &mut self, state: &mut TableState, colors: &WidgetColors, ) -> Response

Render a data table with custom widget colors.

Source

pub fn table_with( &mut self, state: &mut TableState, cell: impl Fn(usize, usize, &str) -> (String, Style) + 'static, ) -> Response

Render a data table with a per-column cell renderer.

cell maps (row_view_index, col_index, raw_cell) to a (content, Style) pair, letting any column carry its own foreground / background / modifiers (a colored badge, a status label, an icon, …). Columns whose closure returns the unchanged raw string with a default Style fall back to the plain string-grid behavior. The closure is 'static (it is invoked during deferred row rendering) and is called once per visible cell per frame.

Sorting, filtering, pagination, width constraints, and multi-row selection all behave exactly as in table; only the per-cell content/style differs.

Available since v0.21.0.

§Example
use slt::{Color, Style, widgets::TableState};
let mut table = TableState::new(
    vec!["Service", "Status"],
    vec![vec!["api", "OK"], vec!["db", "DOWN"]],
);
ui.table_with(&mut table, |_row, col, raw| {
    if col == 1 {
        let color = if raw == "OK" { Color::Green } else { Color::Red };
        (raw.to_string(), Style::new().fg(color).bold())
    } else {
        (raw.to_string(), Style::default())
    }
});
Source

pub fn tabs(&mut self, state: &mut TabsState) -> Response

Render a horizontal tab bar. Handles Left/Right navigation when focused.

The active tab is rendered in the theme’s primary color. If the labels list is empty, nothing is rendered.

Source

pub fn tabs_colored( &mut self, state: &mut TabsState, colors: &WidgetColors, ) -> Response

Render a horizontal tab bar with custom widget colors.

Source

pub fn paginator(&mut self, state: &mut PaginatorState) -> Response

Render a standalone paginator, decoupled from any list or table.

Consumes Left/h/PageUp (previous page) and Right/l/PageDown (next page) when focused, and consumes those key events when handled. Clicking a dot (in PaginatorStyle::Dots) jumps to that page; clicking the left/right half of the counter (in PaginatorStyle::Arabic) goes to the previous/next page. Response::changed is true iff the page changed this frame.

Pass a &mut PaginatorState each frame and use PaginatorState::page_bounds to slice your own data.

§Example
use slt::PaginatorState;

let mut state = PaginatorState::new(42, 10);
ui.paginator(&mut state);
Source

pub fn paginator_colored( &mut self, state: &mut PaginatorState, colors: &WidgetColors, ) -> Response

Render a standalone paginator with custom widget colors.

Behaves exactly like Context::paginator but draws with the provided WidgetColors instead of the theme defaults.

§Example
use slt::{Color, PaginatorState, WidgetColors};

let mut state = PaginatorState::new(20, 5);
let colors = WidgetColors {
    accent: Some(Color::Cyan),
    ..WidgetColors::default()
};
ui.paginator_colored(&mut state, &colors);
Source

pub fn button(&mut self, label: impl Into<String>) -> Response

Render a clickable button. Activation fires via Enter, Space, or mouse click.

The returned Response::clicked flag is set on activation. The button is styled with the theme’s primary color when focused and the accent color when hovered.

Source

pub fn button_colored( &mut self, label: impl Into<String>, colors: &WidgetColors, ) -> Response

Render a clickable button with custom widget colors.

Source

pub fn button_with( &mut self, label: impl Into<String>, variant: ButtonVariant, ) -> Response

Render a styled button variant. Returns true when activated.

Use ButtonVariant::Primary for call-to-action, ButtonVariant::Danger for destructive actions, or ButtonVariant::Outline for secondary actions.

Source

pub fn checkbox( &mut self, label: impl Into<String>, checked: &mut bool, ) -> Response

Render a checkbox. Toggles the bool on Enter, Space, or click.

The checked state is shown with the theme’s success color. When focused, a prefix is added. Render a checkbox toggle.

Source

pub fn checkbox_colored( &mut self, label: impl Into<String>, checked: &mut bool, colors: &WidgetColors, ) -> Response

Render a checkbox toggle with custom widget colors.

Source

pub fn toggle(&mut self, label: impl Into<String>, on: &mut bool) -> Response

Render an on/off toggle switch.

Toggles on when activated via Enter, Space, or click. The switch renders as ●━━ ON or ━━● OFF colored with the theme’s success or dim color respectively. Render an on/off toggle switch.

Source

pub fn toggle_colored( &mut self, label: impl Into<String>, on: &mut bool, colors: &WidgetColors, ) -> Response

Render an on/off toggle switch with custom widget colors.

Source

pub fn select(&mut self, state: &mut SelectState) -> Response

Render a dropdown select. Shows the selected item; expands on activation.

Returns true when the selection changed this frame. Render a dropdown select widget.

Source

pub fn select_colored( &mut self, state: &mut SelectState, colors: &WidgetColors, ) -> Response

Render a dropdown select widget with custom widget colors.

Source

pub fn radio(&mut self, state: &mut RadioState) -> Response

Render a radio button group. Returns true when selection changed. Render a radio button group.

Source

pub fn radio_colored( &mut self, state: &mut RadioState, colors: &WidgetColors, ) -> Response

Render a radio button group with custom widget colors.

Source

pub fn multi_select(&mut self, state: &mut MultiSelectState) -> Response

Render a multi-select list. Space toggles, Up/Down navigates.

Source

pub fn color_picker(&mut self, state: &mut ColorPickerState) -> Response

Render an interactive color picker over the Color model.

Shows a grid of color swatches plus an optional hex-entry field. When focused, the arrow keys / hjkl move the 2D swatch cursor (clamped at the grid edges), Tab toggles between palette and hex entry, and Enter / Space confirms the current color. Returns changed on the exact frames where the selected Color differs from the previous frame. Read the chosen color back via ColorPickerState::selected.

Each swatch is emitted with a full-RGB background; the terminal backend downsamples it to the active ColorDepth on flush, so the picker degrades correctly on 256-color, 16-color, and no-color terminals. Uses the theme’s color_picker slot for border and cursor colors; override per-call with color_picker_colored.

§Example
let mut picker = ColorPickerState::tailwind();
if ui.color_picker(&mut picker).changed {
    let chosen = picker.selected();
    let _ = chosen;
}
Source

pub fn color_picker_colored( &mut self, state: &mut ColorPickerState, colors: &WidgetColors, ) -> Response

Render a color picker with custom WidgetColors.

Behaves exactly like color_picker but draws the border, cursor highlight, and hex field with the supplied colors instead of the theme’s color_picker slot.

§Example
let mut picker = ColorPickerState::tailwind();
let theme = WidgetColors::new().accent(Color::Cyan);
ui.color_picker_colored(&mut picker, &theme);
Source§

impl Context

Source

pub fn tree(&mut self, state: &mut TreeState) -> Response

Render a tree view. Left/Right to collapse/expand, Up/Down to navigate.

Source

pub fn directory_tree(&mut self, state: &mut DirectoryTreeState) -> Response

Render a directory tree with guide lines and tree connectors.

Source§

impl Context

Source

pub fn bar_chart(&mut self, data: &[(&str, f64)], max_width: u32) -> Response

Render a horizontal bar chart from (label, value) pairs.

Bars are normalized against the largest value and rendered with up to max_width characters.

§Example
let data = [
    ("Sales", 160.0),
    ("Revenue", 120.0),
    ("Users", 220.0),
    ("Costs", 60.0),
];
ui.bar_chart(&data, 24);

For styled bars with per-bar colors, see bar_chart_with.

Source

pub fn bar_chart_with( &mut self, bars: &[Bar], configure: impl FnOnce(&mut BarChartConfig), max_size: u32, ) -> Response

Render a bar chart with custom configuration.

Source

pub fn bar_chart_grouped( &mut self, groups: &[BarGroup], max_width: u32, ) -> Response

Render a grouped bar chart.

Each group contains multiple bars rendered side by side. Useful for comparing categories across groups (e.g., quarterly revenue by product).

§Example
use slt::{Bar, BarGroup, Color};
let groups = vec![
    BarGroup::new("2023", vec![Bar::new("Rev", 100.0).color(Color::Cyan), Bar::new("Cost", 60.0).color(Color::Red)]),
    BarGroup::new("2024", vec![Bar::new("Rev", 140.0).color(Color::Cyan), Bar::new("Cost", 80.0).color(Color::Red)]),
];
ui.bar_chart_grouped(&groups, 40);
Source

pub fn bar_chart_grouped_with( &mut self, groups: &[BarGroup], configure: impl FnOnce(&mut BarChartConfig), max_size: u32, ) -> Response

Render a grouped bar chart with custom configuration.

Source

pub fn sparkline(&mut self, data: &[f64], width: u32) -> Response

Render a single-line sparkline from numeric data.

Uses the last width points (or fewer if the data is shorter) and maps each point to one of ▁▂▃▄▅▆▇█.

§Example
let samples = [12.0, 9.0, 14.0, 18.0, 16.0, 21.0, 20.0, 24.0];
ui.sparkline(&samples, 16);

For per-point colors and missing values, see sparkline_styled.

Source

pub fn sparkline_styled( &mut self, data: &[(f64, Option<Color>)], width: u32, ) -> Response

Render a sparkline with per-point colors.

Each point can have its own color via (f64, Option<Color>) tuples. Use f64::NAN for absent values (rendered as spaces).

§Example
use slt::Color;
let data: Vec<(f64, Option<Color>)> = vec![
    (12.0, Some(Color::Green)),
    (9.0, Some(Color::Red)),
    (14.0, Some(Color::Green)),
    (f64::NAN, None),
    (18.0, Some(Color::Cyan)),
];
ui.sparkline_styled(&data, 16);
Source

pub fn line_chart(&mut self, data: &[f64], width: u32, height: u32) -> Response

Render a multi-row line chart using braille characters.

width and height are terminal cell dimensions. Internally this uses braille dot resolution (width*2 x height*4) for smoother plotting.

§Example
let data = [1.0, 3.0, 2.0, 5.0, 4.0, 6.0, 3.0, 7.0];
ui.line_chart(&data, 40, 8);
Source

pub fn line_chart_colored( &mut self, data: &[f64], width: u32, height: u32, color: Color, ) -> Response

Render a multi-row line chart using a custom color.

Source

pub fn area_chart(&mut self, data: &[f64], width: u32, height: u32) -> Response

Render a multi-row area chart using the primary theme color.

Source

pub fn area_chart_colored( &mut self, data: &[f64], width: u32, height: u32, color: Color, ) -> Response

Render a multi-row area chart using a custom color.

Source

pub fn candlestick( &mut self, candles: &[Candle], up_color: Color, down_color: Color, ) -> Response

Render an OHLC candlestick chart.

Source

pub fn heatmap( &mut self, data: &[Vec<f64>], width: u32, height: u32, low_color: Color, high_color: Color, ) -> Response

Render a heatmap from a 2D data grid.

Each cell maps to a block character with color intensity: low values -> dim/dark, high values -> bright/saturated.

§Arguments
  • data - Row-major 2D grid (outer = rows, inner = columns)
  • width - Widget width in terminal cells
  • height - Widget height in terminal cells
  • low_color - Color for minimum values
  • high_color - Color for maximum values
Source

pub fn canvas( &mut self, width: u32, height: u32, draw: impl FnOnce(&mut CanvasContext), ) -> Response

Render a braille drawing canvas.

The closure receives a CanvasContext for pixel-level drawing. Each terminal cell maps to a 2x4 braille dot matrix, giving width*2 x height*4 pixel resolution.

§Example
ui.canvas(40, 10, |cv| {
    cv.line(0, 0, cv.width() - 1, cv.height() - 1);
    cv.circle(40, 20, 15);
});
Source

pub fn chart( &mut self, configure: impl FnOnce(&mut ChartBuilder), width: u32, height: u32, ) -> Response

Render a multi-series chart with axes, legend, and auto-scaling.

width and height must be non-zero. For dynamic sizing, read terminal dimensions first (for example via ui.width() / ui.height()) and pass the computed values to this method.

Source

pub fn scatter( &mut self, data: &[(f64, f64)], width: u32, height: u32, ) -> Response

Renders a scatter plot.

Each point is a (x, y) tuple. Uses braille markers.

Source

pub fn histogram(&mut self, data: &[f64], width: u32, height: u32) -> Response

Render a histogram from raw data with auto-binning.

Source

pub fn histogram_with( &mut self, data: &[f64], configure: impl FnOnce(&mut HistogramBuilder), width: u32, height: u32, ) -> Response

Render a histogram with configuration options.

Source

pub fn qr_code(&mut self, data: impl AsRef<str>) -> Response

Available on crate feature qrcode only.

Render a QR code using half-block characters.

Source

pub fn heatmap_halfblock( &mut self, data: &[Vec<f64>], width: u32, height: u32, low_color: Color, high_color: Color, ) -> Response

Render a heatmap using half-block characters for 2× vertical resolution.

Each terminal cell packs two data rows using with fg for the upper half and bg for the lower half. This doubles the effective vertical resolution compared to heatmap.

§Example
use slt::Color;
let data: Vec<Vec<f64>> = (0..20)
    .map(|r| (0..40).map(|c| ((r * 3 + c * 7) % 20) as f64).collect())
    .collect();
ui.heatmap_halfblock(&data, 40, 10, Color::Rgb(10, 10, 40), Color::Rgb(255, 80, 30));
Source

pub fn candlestick_hd( &mut self, candles: &[Candle], up_color: Color, down_color: Color, ) -> Response

Render a candlestick chart with heavy box-drawing and half-block precision.

Uses for wicks (heavier than ) and / at body edges for sub-cell vertical precision, effectively doubling the price resolution.

Each terminal cell represents two half-cells vertically: the body’s open and close prices snap to the nearest half-cell, so a body that covers an odd number of half-cells terminates with (top half only) or (bottom half only) rather than rounding to a full cell.

§Example
use slt::{Candle, Color};
let candles = vec![
    Candle { open: 100.0, high: 108.0, low: 98.0, close: 105.0 },
    Candle { open: 105.0, high: 112.0, low: 103.0, close: 110.0 },
];
ui.candlestick_hd(&candles, Color::Rgb(38, 166, 91), Color::Rgb(234, 57, 67));
Source

pub fn treemap(&mut self, items: &[TreemapItem]) -> Response

Render a treemap using the squarified layout algorithm.

Each item occupies a rectangle proportional to its value, filled with the item’s color and labeled when space permits.

§Example
use slt::{TreemapItem, Color};
let items = vec![
    TreemapItem::new("Rust", 40.0, Color::Cyan),
    TreemapItem::new("Go", 25.0, Color::Blue),
    TreemapItem::new("Python", 20.0, Color::Yellow),
    TreemapItem::new("Java", 15.0, Color::Red),
];
ui.treemap(&items);
Source

pub fn bar_chart_stacked( &mut self, groups: &[BarGroup], max_height: u32, ) -> Response

Render a stacked bar chart with custom configuration.

Each group’s bars are stacked on top of each other rather than placed side-by-side.

§Example
use slt::{Bar, BarGroup, Color};
let groups = vec![
    BarGroup::new("2023", vec![
        Bar::new("Rev", 100.0).color(Color::Cyan),
        Bar::new("Cost", 60.0).color(Color::Red),
    ]),
    BarGroup::new("2024", vec![
        Bar::new("Rev", 140.0).color(Color::Cyan),
        Bar::new("Cost", 80.0).color(Color::Red),
    ]),
];
ui.bar_chart_stacked(&groups, 20);
Source

pub fn bar_chart_stacked_with( &mut self, groups: &[BarGroup], configure: impl FnOnce(&mut BarChartConfig), max_height: u32, ) -> Response

Render a stacked bar chart with custom configuration.

Uses BarChartConfig for bar width, gap, and max value settings.

Source§

impl Context

Source

pub fn set_scroll_speed(&mut self, lines: u32)

Set how many lines each scroll event moves. Default is 1.

Source

pub fn scroll_speed(&self) -> u32

Get the current scroll speed (lines per scroll event).

Source

pub fn focus_index(&self) -> usize

Get the current focus index.

Widget indices are assigned in the order register_focusable() is called. Indices are 0-based and wrap at focus_count().

Source

pub fn set_focus_index(&mut self, index: usize)

Set the focus index to a specific focusable widget.

Widget indices are assigned in the order register_focusable() is called (0-based). If index exceeds the number of focusable widgets it will be clamped by the modulo in register_focusable.

§Example
// Focus the second focusable widget (index 1)
ui.set_focus_index(1);
Source

pub fn focus_count(&self) -> usize

Get the number of focusable widgets registered in the previous frame.

Returns 0 on the very first frame. Useful together with set_focus_index() for programmatic focus control.

Note: this intentionally reads prev_focus_count (the settled count from the last completed frame) rather than focus_count (the still-incrementing counter for the current frame).

Source

pub fn focus_next(&mut self)

Move keyboard focus to the next focusable widget (wrapping), exactly as pressing Tab would. Honors an active modal’s focus trap. Pairs with set_focus_index / focus_count for programmatic focus control (e.g. an app-level shortcut). Available since v0.21.1.

§Example
// Advance focus on a custom shortcut (e.g. a vim-style 'j').
if ui.key('j') {
    ui.focus_next();
}
Source

pub fn focus_prev(&mut self)

Move keyboard focus to the previous focusable widget (wrapping), exactly as Shift+Tab would. Honors an active modal’s focus trap. Available since v0.21.1.

Source

pub fn focus_next_in_group(&mut self, group: &str)

Move focus to the next focusable widget belonging to the named focus group, wrapping within the group. If focus is currently outside the group it jumps to the group’s first member. No-op if the group had no focusable widgets on the previous frame.

Focus groups are declared with group; this is the scoped counterpart to focus_next for building a focus trap around a panel or sub-form without a modal. Available since v0.21.1.

Source

pub fn focus_prev_in_group(&mut self, group: &str)

Move focus to the previous focusable widget in the named group (wrapping). See focus_next_in_group. Available since v0.21.1.

Source

pub fn capabilities(&self) -> &Capabilities

Available on crate feature crossterm only.

Read-only snapshot of the terminal’s negotiated capabilities (issue #264).

Populated once at session enter via a DA1/DA2/XTGETTCAP probe. This is diagnostics-only: image rendering already routes through the automatic blitter ladder (Kitty > Sixel > sextant > half-block), so app code is never required to branch on the returned value. On a headless backend (e.g. TestBackend) or piped stdout, the probe is skipped and every field is a conservative default.

Available since 0.21.0.

§Example
let caps = ui.capabilities();
// e.g. surface a "truecolor: on" line in a diagnostics panel.
let _ = caps.truecolor;
Source

pub fn widget<W: Widget>(&mut self, w: &mut W) -> W::Response

Render a custom Widget.

Calls Widget::ui with this context and returns the widget’s response.

Source

pub fn error_boundary(&mut self, f: impl FnOnce(&mut Context))

Wrap child widgets in a panic boundary.

If the closure panics, the panic is caught and an error message is rendered in place of the children. The app continues running.

§Example
ui.error_boundary(|ui| {
    ui.text("risky widget");
});
Source

pub fn error_boundary_with( &mut self, f: impl FnOnce(&mut Context), fallback: impl FnOnce(&mut Context, String), )

Like error_boundary, but renders a custom fallback instead of the default error message.

The fallback closure receives the panic message as a String.

§Example
ui.error_boundary_with(
    |ui| {
        ui.text("risky widget");
    },
    |ui, msg| {
        ui.text(format!("Recovered from panic: {msg}"));
    },
);
Source

pub fn region_cache_hits(&self) -> u32

Number of ContainerBuilder::cached regions this frame whose version key was unchanged from the previous frame (cache hits).

Diagnostics for the opt-in streaming cache (issue #273). A region is a hit when its author-supplied version_key matches the value the same call site recorded last frame; it misses on a key change, a new call site, the first frame, or after a terminal resize.

Since 0.21.0.

§Example
ui.container().cached(42, |ui| {
    ui.text("stable chrome");
});
let _hits = ui.region_cache_hits();
Source

pub fn region_cache_misses(&self) -> u32

Number of ContainerBuilder::cached regions this frame whose version key changed (or was new / first-frame / post-resize) — cache misses.

The counterpart to Context::region_cache_hits. See issue #273.

Since 0.21.0.

§Example
ui.container().cached(7, |ui| {
    ui.text("chrome");
});
let _misses = ui.region_cache_misses();
Source

pub fn interaction(&mut self) -> Response

Allocate a click/hover interaction slot and return the Response.

Use this in custom widgets to detect mouse clicks and hovers without wrapping content in a container. Call it immediately before the text, rich text, link, or container that should own the interaction rect. Each call reserves one slot in the hit-test map, so the call order must be stable across frames.

Source

pub fn register_focusable(&mut self) -> bool

Register a widget as focusable and return whether it currently has focus.

Call this in custom widgets that need keyboard focus. Each call increments the internal focus counter, so the call order must be stable across frames.

§Slot reservation by register_focusable_named

If register_focusable_named was called immediately before this call, it has already allocated a slot and bound a name to it; this call reuses that slot instead of allocating a fresh one. That keeps the name binding pointed at the widget the user sees rather than at a dummy slot.

Source

pub fn use_state<T: 'static>(&mut self, init: impl FnOnce() -> T) -> State<T>

Create persistent state that survives across frames.

Returns a State<T> handle. Access with state.get(ui) / state.get_mut(ui).

§Rules
  • Must be called in the same order every frame (like React hooks)
  • Do NOT call inside if/else that changes between frames
§Example
let count = ui.use_state(|| 0i32);
let val = count.get(ui);
ui.text(format!("Count: {val}"));
if ui.button("+1").clicked {
    *count.get_mut(ui) += 1;
}
Source

pub fn use_state_named<T: 'static>( &mut self, id: &'static str, init: impl FnOnce() -> T, ) -> State<T>

Component-local persistent state keyed by a stable id.

Unlike use_state, this is not order-dependent — the value is looked up by id instead of call position. Safe to call inside conditional branches or reusable component functions.

Returns a State<T> handle. Access with state.get(ui) / state.get_mut(ui). Persists across frames.

§Scoping

Keys are &'static str and live in a single global namespace per Context (no automatic per-component scoping). Two calls with the same id in the same frame share the same value, regardless of where they occur in the tree. Pick unique ids — for example, prefix with a component name ("counter::value").

§Naming

The no-suffix form takes an init closure, matching use_state(init) and use_state_keyed(id, init). Use use_state_named_default for the T: Default shorthand.

§Example
fn counter(ui: &mut slt::Context) {
    let count = ui.use_state_named("counter::value", || 0i32);
    ui.text(format!("Count: {}", count.get(ui)));
    if ui.button("+1").clicked {
        *count.get_mut(ui) += 1;
    }
}
Source

pub fn use_state_named_default<T: 'static + Default>( &mut self, id: &'static str, ) -> State<T>

Like use_state_named, but uses Default::default() to initialize the value on first call.

Mirrors use_state_keyed_default: the _default suffix means “no init closure, T: Default required”.

§Example
let value = ui.use_state_named_default::<i32>("counter::value");
ui.text(format!("{}", value.get(ui)));
Source

pub fn use_state_named_with<T: 'static>( &mut self, id: &'static str, init: impl FnOnce() -> T, ) -> State<T>

👎Deprecated since 0.21.0:

Renamed to use_state_named — the no-suffix form now takes the init closure, matching use_state / use_state_keyed.

Deprecated alias for use_state_named.

Deprecated since 0.21.0: the _named family now follows the “no-suffix = init closure” convention so it matches use_state and use_state_keyed. The init-closure form is now spelled use_state_named(id, init); the T: Default shorthand is use_state_named_default.

§Example
// Old: ui.use_state_named_with("counter::value", || 0i32)
let count = ui.use_state_named("counter::value", || 0i32);
ui.text(format!("{}", count.get(ui)));
Source

pub fn animate_bool(&mut self, id: &'static str, value: bool) -> f64

Smoothly animate between 0.0 and 1.0 driven by a boolean.

Returns the current interpolated value (0.0..=1.0). When value is true the result tweens toward 1.0; when false it tweens back toward 0.0. The transition duration defaults to DEFAULT_ANIMATE_TICKS (12 ticks ≈ 200 ms at 60 Hz). Use Context::animate_value for custom duration or non-binary targets.

State is stored in the per-context named-state map under id. The id is &'static str (single global namespace per context), matching Context::use_state_named. Pick a unique key per call site — two animate_bool calls with the same id share state.

On the first call, the value snaps to the target with no visible transition (so widgets that mount in their final state don’t pop).

§Example
let opacity = ui.animate_bool("sidebar::visible", is_open);
// 0.0 ≤ opacity ≤ 1.0; use as alpha or visibility threshold.
§See also
  • animate_value — the underlying primitive this delegates to; use it for a custom duration or a non-binary target.
  • Tween — full control over easing and lifecycle.
Source

pub fn animate_value( &mut self, id: &'static str, target: f64, duration_ticks: u64, ) -> f64

Smoothly animate a f64 value toward target over duration_ticks.

Uses a linear-easing crate::Tween stored implicitly in the per-context named-state map under id. Returns the current interpolated value. On the first call the value snaps to target with no visible transition; on subsequent calls when target changes the tween is rebuilt starting from the current interpolated value, so retargeting mid-flight does not produce a jump.

duration_ticks == 0 snaps immediately to the new target.

§Panics

Panics if id is already bound in the named-state map to a value of a different type (e.g. a use_state_named call reused the same id), since the stored entry then fails to downcast to the internal animation state:

animate_value: id {id} is already used for a different state type

Pick a unique id per call site to avoid the collision.

§Example
let bar_height = ui.animate_value("loading::bar", target_height, 30);
ui.bar(bar_height);
§Comparison with Tween

Use this shorthand when you want zero boilerplate and linear easing is acceptable. For custom easing, a non-static key, or non-tick-based control, construct a crate::Tween explicitly via Context::use_state_named.

§See also
  • animate_bool — boolean-driven shorthand that tweens between 0.0 and 1.0.
  • Tween — explicit easing and lifecycle control.
Source

pub fn schedule(&mut self, id: &'static str, dur: Duration) -> bool

One-shot frame-clock timer (issue #248).

Returns true exactly once — on the first frame at or after dur has elapsed since the first schedule call for id — and false on every other frame, both before and after. Re-arm by calling cancel and then schedule again.

Wall-clock based (std::time::Instant sampled once at frame start), so it works with the default feature set and without the async feature. Precision is bounded by the run loop’s tick_rate (the deadline is observed on the next frame after it elapses), so durations well below the frame cadence are not meaningful.

The id lives in the same per-context namespace as use_state_named: pick a unique key per call site.

§Example
use std::time::Duration;

slt::run(|ui: &mut slt::Context| {
    if ui.schedule("splash::dismiss", Duration::from_millis(800)) {
        // Runs once, ~800ms after the first frame that called this.
        ui.text("Splash dismissed.");
    }
})?;
Source

pub fn every(&mut self, id: &'static str, dur: Duration) -> u32

Recurring frame-clock timer (issue #248).

Returns the number of whole dur intervals that elapsed since the previous frame this id was sampled: 0 on most frames, 1 typically, and > 1 if the frame loop stalled past several intervals — so no ticks are silently dropped. The internal clock advances by exactly the returned number of intervals each frame, so counts never drift.

Wall-clock based and async-free, like schedule.

§Example
use std::time::Duration;

slt::run(|ui: &mut slt::Context| {
    let ticks = ui.every("clock::second", Duration::from_secs(1));
    if ticks > 0 {
        // Advance a once-per-second animation by `ticks` steps.
    }
})?;
Source

pub fn debounce(&mut self, id: &'static str, dur: Duration, dirty: bool) -> bool

Debounce timer — the typeahead / search-as-you-type primitive (#248).

Each frame where dirty == true resets the quiet window to dur. Returns true exactly once on the first frame after dur of quiet (no dirty), then stays false until the next dirty frame re-arms it. This mirrors Textual’s @work(exclusive=True) debounce: collapse a burst of keystrokes so only the final, settled query runs.

Wall-clock based and async-free, like schedule.

§Example
use std::time::Duration;
use slt::TextInputState;

let mut query = TextInputState::with_placeholder("Search...");
slt::run(move |ui: &mut slt::Context| {
    // `resp.changed` is true on the keystroke frame -> the dirty signal.
    let resp = ui.text_input(&mut query);
    // Fire the search only after 250ms of no typing.
    if ui.debounce("search::run", Duration::from_millis(250), resp.changed) {
        // run_search(&query.value());
    }
})?;
Source

pub fn exclusive(&mut self, group: &'static str, id: &str) -> bool

Exclusive-group claim — cancel stale work on supersede (issue #248).

Within a group, only the most-recently-claimed id returns true; once a newer id claims the group, every prior id returns false from then on. Use it to cancel an in-flight typeahead query when a newer query supersedes it: pair with debounce to fire the settled query, then guard the work with exclusive so only the latest claim proceeds.

§Example
use std::time::Duration;

slt::run(|ui: &mut slt::Context| {
    let query_id = "q-42"; // e.g. a per-keystroke sequence id
    if ui.exclusive("search", query_id) {
        // Only the latest claimed query runs; older ones are cancelled.
    }
})?;
Source

pub fn cancel(&mut self, id: &str)

Drop the scheduler slot for id, re-arming it on the next schedule / every / debounce call (issue #248).

Accepts both &'static str and runtime-String ids: clears the slot from the named map and the dynamic-id map.

§Example
use std::time::Duration;

slt::run(|ui: &mut slt::Context| {
    if ui.schedule("retry", Duration::from_secs(5)) {
        // ...
    }
    if ui.key('r') {
        ui.cancel("retry"); // next `schedule("retry", ..)` starts fresh
    }
})?;
Source

pub fn elapsed(&self, id: &str) -> Option<Duration>

Wall-clock time elapsed since id was first scheduled, or None if no live timer slot exists for id (issue #248).

Useful for progress UIs (“retrying in 3s…”) that want the raw elapsed duration rather than a fire/no-fire signal. Measured against the same frame instant the timer methods use.

§Example
use std::time::Duration;

slt::run(|ui: &mut slt::Context| {
    ui.schedule("upload", Duration::from_secs(30));
    if let Some(elapsed) = ui.elapsed("upload") {
        ui.text(format!("Uploading for {}s", elapsed.as_secs()));
    }
})?;
Source

pub fn provide<T: 'static, R>( &mut self, value: T, body: impl FnOnce(&mut Context) -> R, ) -> R

Push a value onto the context stack for the duration of body.

Inside body, child widgets can call use_context::<T>() or try_use_context::<T>() to look up the nearest provided value of type T. Provides cascade in LIFO order: nested calls with the same T shadow outer ones.

The value is automatically popped when body returns — including on panic, so the context stack is always restored.

§Example
struct Theme { accent: slt::Color }
ui.provide(Theme { accent: slt::Color::Red }, |ui| {
    // Any widget here can `let theme = ui.use_context::<Theme>();`
    render_button(ui);
});
Source

pub fn spawn<T: Send + 'static>( &mut self, fut: impl Future<Output = T> + Send + 'static, ) -> TaskHandle<T>

Available on crate feature async only.

Spawn a fire-and-forget async task from inside the frame closure.

Returns a TaskHandle<T> you store and pass to poll on later frames to retrieve the result. This closes the ergonomics gap of the channel pattern (run_async + an external Sender) for the common case: “click a button, kick off one async call, show its result next frame” — without wiring a channel yourself.

Dropping the returned handle cancels the in-flight task. Keep it alive (e.g. in use_state) for as long as you care about the result. Each handle carries a unique id, so two TaskHandle<String> live at the same time never cross their results.

Requires the async feature and an active Tokio runtime — call it inside run_async / run_async_with, which inject the runtime handle.

§Panics

Panics if no Tokio runtime was injected (e.g. when called from the sync run loop or TestBackend without a runtime).

§Example
use slt::{Context, RunConfig, TaskHandle};

async fn fetch() -> String {
    // e.g. an HTTP request
    "result".to_string()
}

slt::run_async_with(RunConfig::default(), |ui: &mut Context, _: &mut Vec<()>| {
    // One handle, stored across frames via `use_state`.
    let handle = ui.use_state(|| None::<TaskHandle<String>>);

    if ui.button("Fetch").clicked && handle.get(ui).is_none() {
        *handle.get_mut(ui) = Some(ui.spawn(async { fetch().await }));
    }

    // Take the handle out of state to poll it: `ui.poll` needs `&mut ui`,
    // which cannot coexist with a `&TaskHandle` borrowed from `ui`'s own
    // state. Put it back if the task is still pending.
    if let Some(h) = handle.get_mut(ui).take() {
        match ui.poll(&h) {
            Some(result) => {
                ui.text(format!("Got: {result}"));
            }
            None => {
                *handle.get_mut(ui) = Some(h);
                ui.text("Loading...");
            }
        }
    }
})?;
Source

pub fn poll<T: 'static>(&mut self, handle: &TaskHandle<T>) -> Option<T>

Available on crate feature async only.

Poll a TaskHandle for its result.

Returns Some(result) exactly once — on the first frame after the task completes — then None on every subsequent call. Returns None while the task is still in flight.

Pairs with spawn. Requires the async feature.

§Example
if let Some(value) = ui.poll(handle) {
    ui.text(format!("done: {value}"));
}
Source

pub fn use_context<T: 'static>(&self) -> &T

Look up the nearest provided value of type T on the context stack.

Searches from the top of the stack (most-recent provide) downward. Returns the first match.

§Panics

Panics if no value of type T is currently provided. Use try_use_context for a non-panicking variant.

Source

pub fn try_use_context<T: 'static>(&self) -> Option<&T>

Like use_context, but returns None instead of panicking when no value of type T is on the stack.

Source

pub fn use_memo<T: 'static, D: PartialEq + Clone + 'static>( &mut self, deps: &D, compute: impl FnOnce(&D) -> T, ) -> Memo<T>

Memoize a computed value. Recomputes only when deps changes.

Returns a Memo<T> index handle, mirroring use_state’s State<T>. The handle holds no borrow of ui, so it composes with later ui.* calls — read the value on demand with .get(ui) / .copied(ui).

Before v0.21.0 this returned &T, a live borrow of &mut Context that could not be held across subsequent ui.* mutations. That form is now use_memo_ref (deprecated). Migrate let x = *ui.use_memo(&d, f); to let x = ui.use_memo(&d, f).copied(ui);.

§Panics

Panics if the hook slot at this call position was previously used for a different hook (a rules-of-hooks / call-order violation), since the type-erased slot then fails to downcast to MemoSlot<T>:

Hook type mismatch at index {idx}: expected {type}. Hooks must be called in the same order every frame.

Keep hook calls in the same order every frame — do not call this inside an if/else whose branch changes between frames.

§Example
let count = ui.use_state(|| 0i32);
let count_val = *count.get(ui);
let doubled = ui.use_memo(&count_val, |c| c * 2);
// The handle survives an intervening `ui.*` call (this is the whole point).
ui.text("doubled:");
ui.text(format!("{}", doubled.copied(ui)));
Source

pub fn use_memo_ref<T: 'static, D: PartialEq + Clone + 'static>( &mut self, deps: &D, compute: impl FnOnce(&D) -> T, ) -> &T

👎Deprecated since 0.21.0:

use_memo now returns a Memo<T> handle; call .get(ui) / .copied(ui)

Deprecated &T-returning form of use_memo.

Deprecated since 0.21.0: use_memo now returns a Memo<T> handle that does not borrow ui, so it composes with later ui.* calls. This alias preserves the original behaviour (returning a &T borrow of ui) for callers that cannot migrate immediately; the borrow keeps ui immutably borrowed until the reference is dropped.

Migrate let x = *ui.use_memo_ref(&d, f); to let x = ui.use_memo(&d, f).copied(ui); (or .get(ui) for a reference).

§Panics

Panics if the hook slot at this call position was previously used for a different hook (a rules-of-hooks / call-order violation), since the type-erased slot then fails to downcast to (D, T):

Hook type mismatch at index {idx}: expected {type}. Hooks must be called in the same order every frame.
§Example
let doubled = *ui.use_memo_ref(&21i32, |c| c * 2);
ui.text(format!("{doubled}"));
Source

pub fn light_dark(&self, light: Color, dark: Color) -> Color

Returns light color if current theme is light mode, dark color if dark mode.

Source

pub fn notify(&mut self, message: &str, level: ToastLevel)

Show a toast notification without managing ToastState.

§Examples
ui.notify("File saved!", ToastLevel::Success);
Source

pub fn use_state_keyed<T: 'static>( &mut self, id: impl Into<String>, init: impl FnOnce() -> T, ) -> State<T>

Component-local persistent state keyed by a runtime string.

Unlike use_state_named, id can be a runtime value such as format!("row-{i}"). The key is converted to String once per call. The hot path (key already present) performs zero string allocations beyond the Into<String> conversion at the call site — first looking up by &str, only allocating a fresh map key on first insert. Together: at most one allocation per call, regardless of cache state.

§When to use
  • Per-item state in a dynamic list where positional use_state would break if items are reordered or filtered.
  • Reusable component functions called with a runtime discriminator.
§Namespace

Keys live in a single global namespace per Context. Prefix them to avoid collisions: format!("my_component::item-{i}").

§Stale entries

Removed items leak their state until the Context is dropped (or the program exits). For long-running sessions with churn, manage state externally via a single Vec<T> in use_state.

§Example
for (i, item) in items.iter().enumerate() {
    let row_state = ui.use_state_keyed(format!("row-{i}"), || ItemState::default());
    // ...
}
Source

pub fn use_state_keyed_default<T: Default + 'static>( &mut self, id: impl Into<String>, ) -> State<T>

Like use_state_keyed, but uses Default::default() to initialize the value on first call.

§Example
let counter = ui.use_state_keyed_default::<i32>(format!("c-{i}"));
Source

pub fn use_effect<D: PartialEq + Clone + 'static>( &mut self, f: impl FnOnce(&D), deps: &D, )

Run a side-effecting closure when deps changes.

On the first frame the hook slot is encountered, f is called unconditionally. On subsequent frames, f is only called when *deps != stored_deps. The hook is positional (same ordering rules as use_state).

§Fire-and-forget semantics

There is no cleanup callback. If setup resources need teardown, store a handle in use_state and drop it on a later frame.

§Caveat: error_boundary re-fire

Effects placed inside an error_boundary scope can re-fire when the boundary catches a panic and rolls back the hook slots. For non-idempotent side effects (network requests, payments) put the effect outside the boundary or guard with an idempotency key.

§Panics

Panics if the hook slot at this call position was previously used for a different hook (a rules-of-hooks / call-order violation), since the type-erased slot then fails to downcast to the deps type D:

Hook type mismatch at index {idx}: expected {type}. Hooks must be called in the same order every frame.
§Common patterns
// Run once on first frame:
ui.use_effect(|_| initialize_logger(), &());

// Run when `selected_tab` changes:
ui.use_effect(|tab| load_tab_data(*tab), &selected_tab);
Source

pub fn register_focusable_named(&mut self, name: &str) -> bool

Register a focusable slot bound to a stable string name.

Returns true if the registered slot currently has focus, exactly like register_focusable — but also records the name → slot mapping so other code can later call focus_by_name and focused_name.

§How the slot is shared with the widget that follows

Every SLT widget that takes focus (button, text_input, tabs, …) internally calls register_focusable() to claim its own slot. To keep the name pointed at the widget the user sees, this call:

  1. allocates a slot eagerly (so the name binding works even when no widget follows — useful for tests and for custom focusable regions),
  2. records the name → slot mapping into the frame’s focus_name_map (first-write-wins on duplicate names within a frame),
  3. reserves the slot id so the next register_focusable() on the same frame reuses it instead of allocating a fresh slot — that’s how text_input(&mut state) placed right after inherits the name.

Names are re-registered each frame; the previous frame’s map is kept under focus_name_map_prev so focus_by_name can resolve a name that has already been registered.

§Two valid usage shapes

Shape A — name a widget that follows immediately (the common pattern; the widget reuses the reserved slot):

let _ = ui.register_focusable_named("search");
let _ = ui.text_input(&mut search_state);
// later: ui.focus_by_name("search") jumps to the text_input

Shape B — register a named focusable region with no inner widget (e.g. a custom render area that handles its own keys when focused):

let focused = ui.register_focusable_named("canvas");
if focused { /* react to keys via key_presses_when */ }
Source

pub fn focus_by_name(&mut self, name: &str) -> bool

Request focus on the named widget.

If the named widget was registered last frame the focus change takes effect at the start of the next frame (one-frame delay is the deferred-command pattern used throughout SLT). If the name has never been registered, the request stays pending: the next frame to register that name receives focus.

Returns true if the call will resolve — i.e. the name was either registered earlier in this frame (via register_focusable_named) or in the previous frame. Returns false only when the name has not been seen by either frame, in which case the request stays pending until some future frame registers the name.

§Example
if ui.button("Find").clicked {
    ui.focus_by_name("search");
}
Source

pub fn focused_name(&self) -> Option<&str>

Return the name of the currently focused widget, if it was registered with register_focusable_named this frame.

Returns None if the focused widget used the unnamed register_focusable API or if no widget has focus.

Source

pub fn key_presses_when( &self, active: bool, ) -> impl Iterator<Item = (usize, &KeyEvent)> + '_

Iterate unconsumed key-press events, gated on active.

When active is false, returns an empty iterator. When active is true, behaves identically to the internal available_key_presses. The returned indices are valid for consume_event.

This is the preferred pattern for focus-gated keyboard handling in custom widgets. Because the iterator borrows self.events immutably, collect the indices first and consume them after the loop:

let focused = ui.register_focusable();
let mut hits: Vec<usize> = Vec::new();
for (i, key) in ui.key_presses_when(focused) {
    if key.code == slt::KeyCode::Enter {
        hits.push(i);
        // ... handle Enter ...
    }
}
for i in hits { ui.consume_event(i); }
Source

pub fn consume_event(&mut self, index: usize)

Mark the event at index as consumed.

Public counterpart to the crate-internal consume_indices. Use this in custom widgets after handling an event yielded by key_presses_when so subsequent widgets don’t react to the same key. Out-of-range indices are silently ignored (matching the iterator-pair semantics).

Source

pub fn static_log(&mut self, line: impl Into<String>)

Append a line that will be flushed to terminal scrollback before the dynamic frame content (issue #233).

Lines accumulated this frame are written via the active runtime — for crate::run_static / crate::run_static_with, they are printed above the inline dynamic area as committed scrollback. For full-screen runtimes (crate::run, crate::run_async) and inline mode (crate::run_inline), the buffer is silently dropped after a debug warning is emitted on the first call per frame, since those modes have no scrollback area to write to.

The headless crate::TestBackend accumulates the lines into the frame state where they can be drained by tests via Context::take_static_log (or by inspecting the buffer when constructing a custom backend).

§Order

static_log may be called any number of times per frame. Lines are flushed in call order, all before the dynamic frame for the same tick.

§Example
ui.static_log("event 1");
ui.static_log(format!("event {}", 2));
ui.text("dynamic content");
Source

pub fn take_static_log(&mut self) -> Vec<String>

Drain and return the queued static-log lines for the current frame (issue #233). Used by tests / external backends to inspect what ui.static_log(...) emitted during a crate::TestBackend::render call.

Source

pub fn publish_keymap( &mut self, name: &'static str, bindings: &'static [(&'static str, &'static str)], )

Publish a widget’s keymap so the framework can show it in the help overlay (issue #236).

Each call registers (name, bindings) for the current frame. Widgets implementing crate::keymap::WidgetKeyHelp typically forward their key_help() slice here:

struct Counter;
impl WidgetKeyHelp for Counter {
    fn key_help(&self) -> &'static [(&'static str, &'static str)] {
        const HELP: &[(&str, &str)] = &[("↑", "increment"), ("↓", "decrement")];
        HELP
    }
}
let counter = Counter;
ui.publish_keymap("counter", counter.key_help());

The registry is reset at the start of every frame (the first call on a new tick clears stale entries). Both calls in the same frame accumulate; calls across frames do not leak.

Source

pub fn published_keymaps(&self) -> &[PublishedKeymap]

Return all keymaps published this frame (issue #236).

Empty if no widget called Context::publish_keymap yet on the current frame. The registry is reset at the start of every frame.

Source

pub fn keymap_help_overlay(&mut self, open: bool)

Render an automatic keymap-help overlay listing every widget keymap published this frame (issue #236).

Pass open = true to render the overlay (typically gated on a ? / F1 keypress). When open is false, this method is a no-op. The overlay groups bindings by widget name and dismisses when the next frame is rendered with open = false.

§Example
const RICHLOG: &[(&str, &str)] = &[("↑/k", "scroll up"), ("↓/j", "scroll down")];
ui.publish_keymap("rich_log", RICHLOG);
// Show the help overlay when '?' is pressed
let show = ui.key('?');
ui.keymap_help_overlay(show);
Source§

impl Context

Intrinsic-size measurement API (v0.21.1).

These read-only queries expose the layout engine’s text-wrapping math and the previous frame’s named-container geometry without changing any rendering path. They let app code reserve space, decide pagination, or position floating UI relative to a widget that was laid out last frame.

Source

pub fn measure_text(&self, text: &str, max_width: Option<u16>) -> (u16, u16)

The intrinsic (width, height_in_rows) text would occupy, in cells.

Reuses the exact word-wrap kernel the layout engine runs (wrap_lines via this crate’s tree module), so the answer always matches what a ui.text(text).wrap() would actually render — width logic is never duplicated here.

  • When max_width is None, the text is measured unwrapped: width is the widest hard-break line, height is the number of '\n'-separated lines (at least 1).
  • When max_width is Some(w) with w > 0, the text is wrapped to w columns; the returned width is the widest wrapped line (<= w) and the height is the wrapped line count.
  • Some(0) is treated like None (no width budget — honor hard breaks only), mirroring the layout kernel’s zero-width contract.

Width is the terminal display width (wide CJK glyphs count as 2, zero-width combining marks as 0). The result is clamped to u16; a pathological line wider than u16::MAX cells saturates rather than wrapping.

§Examples
// Unwrapped: width is the longest line, height the line count.
let (w, h) = ui.measure_text("hello\nworld!", None);
assert_eq!((w, h), (6, 2));

// Wrapped to 5 columns: the long word breaks across rows.
let (w, h) = ui.measure_text("alpha beta gamma", Some(5));
assert!(w <= 5 && h >= 1);
Source

pub fn measured_rect(&self, name: &str) -> Option<Rect>

The Rect a named widget/container occupied on the last completed frame, or None if no group with that name was rendered.

Reads the same name → rect bookkeeping that powers group hover/focus styling (prev_group_rects), captured at the end of the previous frame’s collect pass. Register a name with Context::group:

ui.group("sidebar").border(slt::Border::Rounded).col(|ui| { /* … */ });
// …next frame:
if let Some(r) = ui.measured_rect("sidebar") {
    ui.text(format!("sidebar is {}x{}", r.width, r.height));
}

Returns None on the first frame (nothing measured yet) and for any name that was not rendered as a group(...) last frame. If the same name is used for multiple groups, the first match in render order is returned.

Source§

impl Context

Source

pub fn keymap_match<'m>(&self, map: &'m KeyMap) -> Option<&'m Binding>

Match the current frame’s unconsumed key presses against map and return the first Binding that fires.

This is the KeyMap counterpart to the per-key peek helpers like key and key_code: it scans every unconsumed key-press event for this frame, in arrival order, and returns the first binding in map whose chord matches (see Binding::matches). The event is not consumed — callers can react to the returned binding and, if desired, still let other handlers see the key. Returns None when no press matches any binding.

Like the other peek helpers, this respects the modal/overlay guard: when a modal is active and the caller is outside an overlay, no presses are visible and the method returns None.

§Examples
use slt::{KeyCode, KeyMap, TestBackend};

let km = KeyMap::new()
    .bind('q', "Quit")
    .bind_code(KeyCode::Up, "Move up");

let mut tb = TestBackend::new(20, 3);
tb.run_with_events(vec![slt::Event::key_char('q')], |ui| {
    let hit = ui.keymap_match(&km);
    ui.text(hit.map(|b| b.description.as_str()).unwrap_or("none"));
});
tb.assert_contains("Quit");

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.