Skip to content

File drop

Dropping a file onto the app puts its path where the user is working — the focused text field. This is one of two unrelated "drops" in ratcn; don't mix them up:

  • File drop (this page): the OS file dragged onto the application. Arrives like a paste, goes to the focused component.
  • Dragging: moving components with the mouse, including dropping a dragged element onto a target (MouseKind::Drag/DragEnd).

What a terminal can know

A terminal cannot observe a file drag — no hover position, no drag phases. When a file is dropped onto the terminal window, all the application receives is the file's path, pasted as text. That is why TUIs like Claude Code take drops in the message box: the drop is a paste, and the paste goes to the focused field. Detecting that a paste is path-shaped (to render a file pill, say) is app policy on top of an ordinary paste.

ratcn keeps its file-drop interface exactly this minimal, on every backend:

  • Event::FileDrop(Vec<String>) — just the dropped paths (file names in the browser, which never exposes paths). No position, no drag phases.
  • It routes like a paste: down the focus path to the focused component.

Fields take drops out of the box

Input and TextArea handle FileDrop when focused: by default the paths land as text at the cursor — identical to what a native terminal's paste-of-a-path produces, so both backends behave the same with no wiring. .on_drop(...) overrides the insert with an app message (attach the file rather than insert its path).

Drag a file from your desktop onto the demo: its name lands as text at the focused field's cursor. Tab to the other field and drop again — the drop follows focus, exactly as in a terminal. Neither field carries any drop wiring.

Where the event comes from

  • Native terminals: usually nowhere — the drop already arrives as Event::Paste, and the focused field inserts it. An app that wants on_drop semantics natively constructs Event::FileDrop from a paste it recognizes as a path (the heuristic is the app's).
  • Browser demos: two small DOM listeners — dragover calling only preventDefault() (what makes the browser allow a drop at all; nothing is forwarded, since like a terminal the app can't see the drag), and drop collecting the file names into Event::FileDrop. See the demo's main.rs.