Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Augani/kael/llms.txt

Use this file to discover all available pages before exploring further.

Kael gives you precise control over every window your application creates. You open windows through cx.open_window, receive a typed WindowHandle<V> you can hold on to, and use the Window context to activate, hide, close, or redirect focus at any point during your app’s lifetime. All window configuration flows through a single WindowOptions struct, so you have one place to describe size, position, decorations, background appearance, and more.

Opening a window

Call cx.open_window with a WindowOptions value and a closure that returns the root view. The closure receives a mutable Window and App, mirroring the signature of your component’s render method.
use kael::prelude::*;

fn main() {
    Application::new().run(|cx| {
        cx.open_window(
            WindowOptions {
                window_bounds: Some(WindowBounds::centered(
                    size(px(900.), px(600.)),
                    cx,
                )),
                titlebar: Some(TitlebarOptions {
                    title: Some("My App".into()),
                    appears_transparent: false,
                    traffic_light_position: None,
                }),
                ..WindowOptions::default()
            },
            |_window, cx| cx.new(|_| MyView),
        )
        .unwrap();
    });
}
cx.open_window returns anyhow::Result<WindowHandle<V>>. Unwrap or propagate the error — it fails only if the platform cannot create a native window.

WindowOptions fields

FieldTypeDefaultDescription
window_boundsOption<WindowBounds>NoneInitial position and size. None inherits the platform default.
titlebarOption<TitlebarOptions>transparent titlebarTitle string, transparent mode, and traffic-light position (macOS).
focusbooltrueWhether the window takes focus on creation.
showbooltrueWhether the window is visible on creation.
kindWindowKindNormalNormal or Overlay.
is_movablebooltrueWhether the user can drag the window.
is_resizablebooltrueWhether the user can resize the window.
is_minimizablebooltrueWhether the user can minimize the window.
display_idOption<DisplayId>NoneTarget display. None uses the main display.
window_backgroundWindowBackgroundAppearanceOpaqueBackground rendering mode.
app_idOption<String>NoneDesktop-environment app grouping identifier (Linux).
window_min_sizeOption<Size<Pixels>>NoneMinimum window dimensions.
window_decorationsOption<WindowDecorations>NoneClient- or server-side decorations (Wayland only).
tabbing_identifierOption<String>NoneNative tab group name (macOS 10.12+).
mouse_passthroughboolfalsePass mouse events to windows below this one.
parentOption<AnyWindowHandle>NoneParent window for child/panel windows.

Controlling size and position

WindowBounds wraps a Bounds<Pixels> and describes whether the window opens windowed, maximized, or fullscreen:
use kael::prelude::*;

// Center a 1 200 × 800 window on the primary display
let bounds = WindowBounds::centered(size(px(1200.), px(800.)), cx);

// Open maximized, restoring to 800 × 600
let bounds = WindowBounds::Maximized(Bounds::default());

// Open fullscreen
let bounds = WindowBounds::Fullscreen(Bounds::default());

Window appearance

WindowAppearance

WindowAppearance reflects the OS-level appearance applied to a window. You read the current value from window.appearance() and react to changes via window.observe_window_appearance.
use kael::{WindowAppearance};

// In your render method
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
    let bg = match window.appearance() {
        WindowAppearance::Light | WindowAppearance::VibrantLight => rgb(0xffffff),
        WindowAppearance::Dark  | WindowAppearance::VibrantDark  => rgb(0x1e1e1e),
    };

    div().w_full().h_full().bg(bg)
}
VariantDescription
LightStandard light mode (aqua on macOS).
VibrantLightLight mode with vibrant/translucent effects (NSAppearanceNameVibrantLight).
DarkStandard dark mode (darkAqua on macOS).
VibrantDarkDark mode with vibrant effects (NSAppearanceNameVibrantDark).

WindowBackgroundAppearance

Set window_background in WindowOptions to control how the window composites against the desktop:
use kael::WindowBackgroundAppearance;

WindowOptions {
    window_background: WindowBackgroundAppearance::Blurred,
    ..WindowOptions::default()
}
VariantDescription
Opaque (default)Solid background; content behind the window is not drawn.
TransparentStandard alpha transparency.
BlurredTransparent with platform blur (not always supported).
You can also change the background after the window is open:
window.set_background_appearance(WindowBackgroundAppearance::Blurred);

WindowHandle<V> — holding a reference to a window

cx.open_window returns a WindowHandle<V> where V is the root view type. The handle is Copy + Clone and lets you interact with the window from anywhere in your app.
use kael::prelude::*;

struct AppState {
    main_window: WindowHandle<MainView>,
}

// Later, from an async task or another window:
app_state.main_window.update(cx, |_view, window, _cx| {
    window.activate_window();
})?;
Key methods on WindowHandle<V>:
MethodDescription
.update(cx, |view, window, cx| …)Mutate the root view and access Window.
.read(cx)Borrow the root view immutably.
.read_with(cx, |view, cx| …)Borrow with a closure.
.entity(cx)Obtain the underlying Entity<V>.
AnyWindowHandle is the type-erased counterpart, used when the root type is not known statically.

Multi-window management

You can open as many windows as you like. Keep their handles in your application state to coordinate between them.
use kael::prelude::*;

struct App {
    windows: Vec<WindowHandle<PanelView>>,
}

impl App {
    fn open_panel(&mut self, cx: &mut kael::App) {
        let handle = cx
            .open_window(
                WindowOptions {
                    window_bounds: Some(WindowBounds::centered(size(px(400.), px(300.)), cx)),
                    focus: true,
                    ..WindowOptions::default()
                },
                |_window, cx| cx.new(|_| PanelView),
            )
            .unwrap();

        self.windows.push(handle);
    }
}
cx.windows() returns all currently open window handles if you need to iterate over them without keeping your own list.

Closing windows

Call window.remove_window() from inside any Window context to close the window:
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
    button("Close")
        .on_click(cx.listener(|_this, _event, window, _cx| {
            window.remove_window();
        }))
}

Focus management

Use window.focus(&handle) to move keyboard focus to a focusable element, and window.focused(cx) to query which element currently holds focus.
// Move focus to a specific element
window.focus(&self.search_input_focus);

// Query the currently focused handle
if let Some(handle) = window.focused(cx) {
    // ...
}
To bring the window itself to the foreground at the platform level:
window.activate_window();

Overlay windows and click-through

Set kind: WindowKind::Overlay to create a floating overlay that draws above normal windows. Combine it with mouse_passthrough: true so that click events fall through to whatever is beneath:
use kael::{WindowKind, WindowOptions};

cx.open_window(
    WindowOptions {
        kind: WindowKind::Overlay,
        mouse_passthrough: true,
        show: true,
        focus: false,
        ..WindowOptions::default()
    },
    |_window, cx| cx.new(|_| HudOverlay),
)
.unwrap();
You can toggle pass-through at runtime:
window.set_mouse_passthrough(true);
Overlays are useful for HUD elements, screen annotations, or translucent panels that sit above other content without stealing mouse input.

Build docs developers (and LLMs) love