What it is
A drag-and-drop target for attaching files to a form: drop a file or click to browse, and it appears in a list below with a remove control. It does not upload anywhere itself — attaching a file only adds it to local state and reports the full list back through a callback.Live example
Exports
Choose FileUpload when
- A reader needs to attach one or more files to something they’re submitting, and dragging a file onto a target (or clicking to browse) is a natural way to do it.
- The set of accepted files is a small, add-and-remove list shown in place — not a long-running upload with progress reporting.
Choose something else when
Anatomy
The drop target and the file list are mutually exclusive — verified directly from source, which
renders one or the other, never both. There is no “add another file” affordance once the list
is showing other than the same target reappearing when the list is emptied.
Edge and failure states
Verified directly against the component’s own test suite, not inferred:Tokens
Verified directly fromDropzone.tsx — no per-component token emitter exists yet for this
concept, so this table is hand-confirmed rather than generated.
Composition
Renders standalone — verified against source, it accepts no label prop and does not compose with FieldLabel the way other fields in this category do. A caller wanting a labeled field must wrap it with a label themselves; nothing in this component or inFormInput does that composition today — see
Open issues.
Content
Accessibility
- The visible primary and secondary text are not confirmed to be programmatically associated
with the underlying file input — no
aria-labelledbyor<label>wiring was found in source. Whether a screen reader announces the drop target’s purpose is unconfirmed. - No accessible name is required or validated for the component as a whole — there is no
labeloraria-labelprop. - The remove control is a clickable icon with a keyboard handler in its test mock, but
production source renders it as a plain icon with an
onClick, not a<button>— whether it is keyboard-reachable in the shipped component (not just the test mock) is unconfirmed.
Constraints
Known issues
FileUpload: open issues
Divergences, open decisions, and undocumented gaps for FileUpload.
Why it works this way
Silent rejection is a real gap, not a hidden feature. Nothing about drag-and-drop upload requires failing quietly — the component simply doesn’t wire upuseDropzone’s own
fileRejections callback, which would carry exactly this information. Restating the
restriction in secondaryText is the only mitigation available until that’s addressed, which
is why TITAN-UPLOAD-01 exists as a constraint rather than a suggestion.
Status
Related
- Form — the shared field-composition pattern this component does not participate in
- FieldLabel — for labeling this component by hand, since it has no built-in label