Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Gestures

Kael provides built-in gesture recognizers for touch and pointer interactions. Before relying on tablet-style input, check the platform capability report:

#![allow(unused)]
fn main() {
let input = CapabilityCheck::new()
    .require(PlatformFeature::PrecisionPointerInput)
    .prefer_available(PlatformFeature::GestureInput)
    .prefer_available(PlatformFeature::TouchInput)
    .prefer_available(PlatformFeature::PenInput)
    .evaluate(&CapabilityReport::current());
}

Pointer, scroll, and magnify gestures are the portable baseline today. Direct touch contact streams and pen pressure/tilt metadata are reported separately so apps can provide mouse/keyboard fallbacks when a backend does not expose them.

Pan gesture

Detect drag/pan movements with velocity tracking:

#![allow(unused)]
fn main() {
use kael::gesture::PanGesture;

let pan = PanGesture::new()
    .min_distance(px(5.0))
    .on_start(|position, _window, _cx| { /* drag started */ })
    .on_update(|delta, velocity, _window, _cx| { /* dragging */ })
    .on_end(|velocity, _window, _cx| { /* drag ended */ });
}

Swipe gesture

Detect directional swipes:

#![allow(unused)]
fn main() {
use kael::gesture::SwipeGesture;

let swipe = SwipeGesture::new()
    .on_swipe(|direction, _window, _cx| {
        match direction {
            SwipeDirection::Left => { /* swipe left */ },
            SwipeDirection::Right => { /* swipe right */ },
            SwipeDirection::Up => { /* swipe up */ },
            SwipeDirection::Down => { /* swipe down */ },
        }
    });
}

Pinch gesture

Zoom/scale with pinch-to-zoom or Ctrl+scroll:

#![allow(unused)]
fn main() {
use kael::gesture::PinchGesture;

let pinch = PinchGesture::new()
    .on_pinch(|scale, center, _window, _cx| {
        // scale: f64 (1.0 = no change, >1 = zoom in, <1 = zoom out)
        // center: Point<Pixels> (pinch center point)
    });
}

Drag and drop

File drop (from OS)

#![allow(unused)]
fn main() {
let filter = FileDropFilter::video().max_files(1);

div()
    .id("drop-zone")
    .can_drop_external(filter.clone())
    .on_external_drop(move |data, _window, _cx| {
        if let Some(paths) = data.accepted_paths_by(&filter) {
            for path in paths {
                /* import or open path */
            }
        }
        if let Some(text) = data.text_value() {
            /* handle dropped text */
        }
        for url in data.urls() {
            /* handle dropped URL */
        }
    })
}

Operating-system file drops are translated into Kael's typed drag/drop system as ExternalPaths for file-only payloads and ExternalDropData when text or URLs are present. Use can_drop_external(filter) and on_external_drop(...) to handle both shapes through one browser-like payload. Presets are available for common file cases: FileDropFilter::single_file(), .images(), .audio(), .video(), and .media().

For browser-style integrations that can carry text or URLs alongside files, normalize to ExternalDropData:

#![allow(unused)]
fn main() {
let data = ExternalDropData::from_paths([path])
    .with_text("Dropped label")
    .with_url("https://example.com/item");

if let Some(paths) = data.accepted_paths_by(&FileDropFilter::images()) {
    /* import image paths */
}

let from_active_drag = ExternalDropData::from_drag_value(value);

let from_uri_list = ExternalDropData::from_uri_list(
    "file:///tmp/poster.png\nhttps://example.com/item\n",
);
let from_text = ExternalDropData::from_plain_text("https://example.com/item");
}

Native OS file-only drops still emit ExternalPaths for compatibility. Drops that carry plain text or URLs emit ExternalDropData on macOS, Windows, and Linux text/uri-list paths. Use ExternalDropData for custom platform integrations, WebView bridge messages, and tests that need DataTransfer-like files / text / urls payloads.

Sortable reordering

See SortableList for drag-to-reorder within lists.

Scroll events

#![allow(unused)]
fn main() {
div()
    .id("canvas")
    .on_scroll_wheel(|event, _window, _cx| {
        // event.delta: ScrollDelta (Pixels or Lines)
        // event.modifiers: Modifiers (detect Ctrl for zoom)
    })
}