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
| | | |
|---|
| | Text shown on the browse button. | Required. Use an explicit verb such as "Browse" or "Choose file". |
| | Display text for the chosen file. | If None, the widget shows "No file selected". |
| | 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.