Drag and Drop
Use DragArea and DropArea to move data between parts of the UI with a drag-and-drop gesture. On platforms that support it, a DropArea also accepts drops from other applications.
The payload is a data-transfer value, which abstracts over the file-type transfer mechanisms supported by each platform.
data-transfer values are opaque in Slint code:
construct and read them via callbacks implemented in the host language.
Example
Section titled “Example”export global Api { pure callback string-to-transfer(string) -> data-transfer; pure callback transfer-to-string(data-transfer) -> string; pure callback can-drop(data-transfer) -> bool;}
export component Example inherits Window { width: 300px; height: 200px;
VerticalLayout { spacing: 8px; padding: 8px;
Rectangle { background: #f0c000; DragArea { data: Api.string-to-transfer("Hello World"); } Text { text: "Drag me"; } }
Rectangle { background: drop.contains-drag ? #80e080 : #a0a0a0; drop := DropArea { can-drop(event) => { Api.can-drop(event.data) ? DragAction.copy : DragAction.none } dropped(event) => { debug("Got: ", Api.transfer-to-string(event.data)); return event.proposed-action; } } Text { text: "Drop here"; } } }}Both can-drop and dropped return a DragAction: DragAction.copy, DragAction.move, DragAction.link to accept with that action, or DragAction.none to reject. can-drop runs during hover (drives the cursor and current-action); dropped runs on release and the returned action is what gets reported back to the source via drag-finished.
Drag actions
Section titled “Drag actions”A DragArea declares which actions it permits (allow-copy, allow-move, allow-link) and a preferred-action that applies when no modifier is pressed.
The target picks the final action in can-drop (for hover) and dropped (final answer), the runtime clamps each against the source’s allowed set, and when the drop completes the source’s drag-finished(action) fires so a “move” source can remove the original data.
DragArea { data: Api.make-data(); allow-copy: false; allow-move: true; preferred-action: DragAction.move; // Dim the source while the drag is in flight. opacity: self.dragging ? 0.4 : 1.0; drag-finished(action) => { if action == DragAction.move { Api.remove-source(); } }}
DropArea { can-drop(event) => event.allow-move ? DragAction.move : DragAction.none; dropped(event) => { Api.accept-drop(event.data); return event.proposed-action; }}The hovering target’s chosen action is also exposed as current-action, useful for visual feedback (a different cursor, icon, or highlight per action).
fn main() { let app = Example::new(); // For simple plaintext and image transfers, a simple conversion is supplied // which handles the common case. let api = app.global::<Api>(); api.on_string_to_transfer(Into::into); // A helper for reading plaintext from a `DataTransfer` is also supplied. api.on_transfer_to_string(|data| data.fetch_plaintext().unwrap_or_default()); api.on_can_drop(|data| { // This helper abstracts over various "plaintext" MIME types data.has_plaintext() }); // ...}// `DataTransfer` is currently not fully implemented in C++import * as slint from "slint-ui";
const ui = slint.loadFile(new URL("example.slint", import.meta.url));const window = new ui.Example();
window.Api.string_to_transfer = (text) => { const transfer = new slint.DataTransfer(); transfer.setPlaintext(text); return transfer;};
// A helper for reading plaintext from a `DataTransfer` is also supplied.window.Api.transfer_to_string = (data) => data.fetchPlaintext() ?? "";
// This helper abstracts over various "plaintext" MIME typeswindow.Api.can_drop = (data) => data.hasPlaintext;import slintfrom slint import DataTransfer
class App(slint.loader.example.Example):
@slint.callback(global_name="Api", name="string-to-transfer") def string_to_transfer(self, text: str) -> DataTransfer: transfer = DataTransfer() transfer.set_plaintext(text) return transfer
# A helper for reading plaintext from a `DataTransfer` is also supplied. @slint.callback(global_name="Api", name="transfer-to-string") def transfer_to_string(self, data: DataTransfer) -> str: return data.fetch_plaintext() or ""
# This helper abstracts over various "plaintext" MIME types @slint.callback(global_name="Api", name="can-drop") def can_drop(self, data: DataTransfer) -> bool: return data.has_plaintext© 2026 SixtyFPS GmbH