Skip to content

File upload / dropzone

In review
Live · web

Dropzone: tab to it (Enter / Space), click Browse, or toggle drag-over

Drag files hereor browse · TS, JSON, YAML, images · up to 10.0 MB each
  • session-state.tsReady to upload18 KB
  • tokens.jsonReady to upload6 KB
  • facet-bg.pngReady to upload1.4 MB
  • cluster-dump.bin Too large: 40.3 MB (max 10.0 MB)40.3 MB
0 uploaded · 3 pending

Drag-over highlight: force the active state

// Web: React, consuming @dizyx/nockerl-tokens. (Web is the laggard platform. Spec + live demo,
// not yet exported from @dizyx/nockerl-react; promotion is tracked.)
export function AttachPanel() {
return (
<FileUpload
accept={['.ts', '.json', '.yaml', 'image/*']}
multiple
maxSize={10 * 1024 * 1024}
onFiles={(files) => files.forEach(uploadFile)}
onReject={(file, reason) => toast(`${file.name}: ${reason}`)}
/>
);
}
PropTypeDefaultDescription
onFiles *(files: File[]) => voidCalled with the accepted files from a drop or the browse picker.
acceptstring[]Allowed extensions / MIME globs (e.g. .ts, image/*). Anything else is rejected with a reason.
multiplebooleantrueAllow selecting more than one file at a time.
maxSizenumberPer-file byte cap. Over-size files render the rejected treatment (⚠ + reason), never silently dropped.
onReject(file: File, reason: string) => voidCalled for each file that fails the accept / maxSize checks.
disabledbooleanfalseInert + clearly-seen dropzone (never faded to invisible). Browse + drop are blocked.
Cross-platform drift (tracked for reconciliation)

The dropzone, file list, per-file progress, and success / error / rejected states are web-only today, designed originally from the laws + the Button / TextField / progress vocabulary, since the apps don’t ship them:

  • Android attaches images only through the system photo picker (PickMultipleVisualMedia) and shows dismissable thumbnail chips (an X in the error color). No generic files, no size, no drag-drop, no per-file progress.
  • Voice (macOS) ships no file affordance at all; the Swift code/params above are the intended .fileImporter + .dropDestination API.
  • The signature dropzone reuses the recessed-well + dashed-border look from the text field; the progress bar reuses the gauge track; browse/upload reuse the button ladder, so when the apps adopt it, it already matches.