Dropzone

Dropzone is the richer drag-and-drop surface helper.
Use it when a part of the screen should visibly respond as something is dragged over it, then handle the eventual drop. Typical examples are attachment areas, upload panels, and kanban columns that highlight as the user drags over them.

Example

use fission::prelude::*;

let widget: Widget = Dropzone {
child: upload_panel_node,
on_drag_enter: Some(with_reducer!(ctx, SetHoveringUpload(true), on_set_hovering_upload)),
on_drag_leave: Some(with_reducer!(ctx, SetHoveringUpload(false), on_set_hovering_upload)),
on_drop: Some(ctx.bind(
    FilesDropped,
    reduce_with!((|state: &mut ComposerState, _action: FilesDropped, ctx| {
        if let Some(paths) = ctx.input.as_drop_paths() {
            state.attachments.extend(paths.iter().cloned());
        }
    })),
)),
}
.into();
Here the hover state lives in GlobalState, so the next build can re-render the dropzone with a highlight border.

Field table

Field
Type
Meaning
Notes / default behavior
child
Widget
Visible content wrapped by the drop surface.
Required.
on_drop
Option<ActionEnvelope>
Action dispatched when something is dropped on the surface.
Read external paths with ctx.input.as_drop_paths() or internal bytes with ctx.input.as_internal_drop().
on_drag_enter
Option<ActionEnvelope>
Action dispatched when a drag enters the bounds.
Useful for setting hover state in GlobalState.
on_drag_leave
Option<ActionEnvelope>
Action dispatched when a drag leaves the bounds.
Useful for clearing hover state.

Internal drags versus file drops

Dropzone sits at the point where two kinds of drag input can meet. Internal drags, started by Draggable, arrive as raw bytes. External file drops arrive as host-provided file paths. The widget does not merge those models for you. Your reducer decides which input it expects and how to decode it.

Specific advice

Keep visual hover feedback in state, not in a hidden mutable local flag. That way a reconvert, test harness, or target-level snapshot sees the same dropzone state the user sees.

Production checklist

For Dropzone, review the fields that change behavior before treating the widget as finished: child, on_drop, on_drag_enter, on_drag_leave. The goal is to make the product rule visible in state and actions, not hidden inside ad-hoc construction code.
Bind on_drop, on_drag_enter, on_drag_leave to explicit reducer actions and test that the reducer handles unavailable, duplicate, or invalid input safely.
When child widgets are generated from data, give reordered or filtered rows an explicit WidgetId so retained local state and scroll behavior do not drift between items.
Check the semantics tree for the user-facing label or role that makes this widget understandable without relying only on pixels.
Add at least one component or harness test that confirms the visible text, semantic role, action dispatch, and layout constraint that matter for this widget in context.
If a screen starts repeating the same Dropzone setup, extract a named component around this widget. That keeps the reference API small while making product code easier to read and safer for generated code to copy.
Draggable, DragTarget, FormControl, and GestureDetector.
Fission
A cross-platform, GPU-accelerated user interface framework for Rust. MIT licensed.
Copyright (c) 2026 Fission
Ready to use today. Widget APIs are expected to remain stable; some runtime and shell APIs may change before 1.0.0.
Fission 0.7.0