FileUpload

FileUpload is the small file-picking helper in the authoring widget set.
It gives you a familiar browse button and a text area that shows the currently selected file name. It does not open the operating system file picker by itself. In Fission, that host work belongs in an explicit effect, usually triggered from the reducer after on_browse fires.

Example

use fission::prelude::*;

let widget: Widget = FileUpload {
label: "Browse".into(),
selected_file: view.state().attachment_name.clone(),
on_browse: Some(with_reducer!(ctx, PickAttachment, on_pick_attachment)),
}
.into();
A common next step is for on_pick_attachment to ask the runtime for a file picker capability, then store the chosen file name and DataStreamId in state when the capability returns.

Field table

Field
Type
Meaning
Notes / default behavior
label
String
Text shown on the browse button.
Required. Use an explicit verb such as "Browse" or "Choose file".
selected_file
Option<String>
Display text for the chosen file.
If None, the widget shows "No file selected".
on_browse
Option<ActionEnvelope>
Action fired when the browse button is pressed.
Defaults to None. The reducer usually emits a file-picker capability from here.

How it fits into the state and effect loop

The widget handles presentation only. The full flow usually looks like this: the user presses browse, the widget dispatches on_browse, the reducer asks ctx.effects to invoke a host file-picker capability such as PICK_OPEN_FILES, and a later success action stores the chosen file metadata and stream handle in GlobalState. The next conversion then passes a new selected_file string back into the widget.
File contents are exposed as a FissionDataStream, not as a Vec<u8> in the reducer payload. Pass the PickedFile::stream handle to a job or service if the app needs to parse, upload, or preview the file.
The desktop shell provides a default PICK_OPEN_FILES provider on macOS, Windows, and Linux. Other shells may register their own provider; when no native picker is available, the capability reports an unsupported host error rather than fabricating bytes.
This separation is why file picking remains deterministic inside the core runtime. The widget describes intent, while the host interaction happens explicitly outside the reducer.

Specific advice

Show a meaningful filename or summary after selection so the user can confirm what happened. Also remember that this widget displays one string; if your flow supports multiple files, store and render a deliberate summary such as "3 files selected" or a separate attachments list next to it.

Production checklist

For FileUpload, review the fields that change behavior before treating the widget as finished: label, selected_file, on_browse. The goal is to make the product rule visible in state and actions, not hidden inside ad-hoc construction code.
Bind on_browse to explicit reducer actions and test that the reducer handles unavailable, duplicate, or invalid input safely.
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 FileUpload 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.
Dropzone, Button, FormControl, How do I do file uploads in Fission?, and Resources and async.
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