Components / Controls
FileDrop
A place to add files: drop them on it, or press its button to pick them. It checks each file and explains what it turned away.
When to useLink to "When to use"
- Uploads, imports and attachments, especially where people may drag files from their desktop.
Use something else when:
- a single button is enough (a small toolbar action): a Button that opens a FileInputBase
UsageLink to "Usage"
import { FileDrop } from "@arshad-shah/cynosure";
<FileDrop multiple accept=".pdf,image/*" maxSize={5_000_000} hint="PDF or images, up to 5 MB" onFiles={upload} />onFiles receives the files that passed. Without multiple only the first file is taken.
ChecksLink to "Checks"
accept (extensions, MIME types and type/*), maxSize (bytes) and maxFiles decide what is taken. Each refusal is listed in the zone and passed to onReject with its reason: type, size or count.
The whole windowLink to "The whole window"
With target="window", files dropped anywhere in the window are taken, for an app that opens whatever is dropped on it. An overlay covers the page while files are dragged in; text and links dragged over the page are left alone.
<FileDrop target="window" accept=".har,.json" onFiles={open} />Your own picker and a list of chosen filesLink to "Your own picker and a list of chosen files"
onPick replaces the browser's file dialog with your own picker (Electron's dialog over IPC), as PathField's onPick does: the button calls it and is busy until it settles. It resolves with what was chosen, files or paths, or null when cancelled; a cancel or a failure changes nothing. Chosen files are checked like dropped ones and arrive in onFiles; chosen paths arrive in onPaths. Dropped files still arrive in onFiles.
value lists what has been chosen, files by name and paths as given, each with a remove button when onRemove is set. The list is yours: add to it from onPaths and onFiles, take out what onRemove(item, index) reports. A removal is announced, and focus moves to the next remove button, so several can be removed in a row.
const [chosen, setChosen] = useState<string[]>([]);
<FileDrop
multiple
value={chosen}
onPick={() => window.api.pickFiles()} // Promise<string[] | null>
onPaths={(paths) => setChosen([...chosen, ...paths])}
onFiles={(files) => setChosen([...chosen, ...files.map((f) => f.name)])}
onRemove={(_, index) => setChosen(chosen.filter((_, i) => i !== index))}
/>value is display only: a form submits the files in the native input, those picked or dropped here.
FormsLink to "Forms"
With name, the form submits the accepted files, whether they were dropped or picked: FileDrop keeps its native file input in step.
PropsLink to "Props"
| Prop | What it does | Type | Default |
|---|---|---|---|
onFiles | Called with the files that passed the checks. | ((files: File[]) => void) | |
onPick | Replaces the browser's file dialog with your picker (Electron's dialog.showOpenDialog over IPC), as PathField's onPick: the button calls it and is busy until it settles. It resolves with what was chosen, or null when it was cancelled; a cancel or a failure (the promise rejects) changes nothing. Chosen files are checked as dropped ones are and arrive in onFiles, chosen paths in onPaths. Dropped files still arrive in onFiles. | (() => Promise<readonly (File | string)[] | null>) | |
onPaths | Called with the paths onPick chose (strings, as your picker gave them); put them in value to list them. | ((paths: string[]) => void) | |
value | The chosen files or paths, listed in the zone by name (a File's name, a path as given), each with a remove button when onRemove is set. Controlled: add to it from onFiles or your own picker. Display only: the native input (and so a form) holds only files picked or dropped here. | readonly (string | File)[] | |
onRemove | Called with a chosen item and its index when its remove button is pressed; take it out of value. | ((item: File | string, index: number) => void) | |
onReject | Called with the files that did not, and why (they are also listed in the zone). | ((rejections: FileRejection[]) => void) | |
accept | File types, as for <input accept>: ".pdf,image/*". | string | |
multiple | Take more than one file at a time. | boolean | |
maxSize | Largest file in bytes. | number | |
maxFiles | Most files in one go (with multiple). | number | |
target | zone (default): files are dropped on the zone. window: files dropped anywhere in the window are taken, and an overlay covers the page while they are dragged in (for an app whose whole page is a drop target). | "zone" | "window" | |
hint | Shown under the prompt, e.g. "PNG or JPG, up to 5 MB". | ReactNode | |
name | Name the accepted files are submitted under in a form. | string | |
form | Id of the form it belongs to, when it is not inside that form. | string | |
required | Marks the file input as required for form validation. | boolean | |
disabled | Turns off dropping and the button. | boolean | |
size | Size of the zone and its button. Default "md". | Size | "md" |
labels | Replace the built-in English text. | Partial<FileDropLabels> | |
className | Added to the root element, for layout. | string | |
style | Layout only. Restyle through --cy-file-drop-* tokens. | CSSProperties |
Generated from the type definitions in @arshad-shah/cynosure 0.5.0.
Behaviour and accessibilityLink to "Behaviour and accessibility"
- The button is the way in. Keyboard, touch and screen reader users pick files with it; dropping is a shortcut for pointer users. The native input is hidden and out of the tab order.
- Hint: read as the button's description.
- Chosen files: a list named by
labels.files; each remove button is named "Remove " and the item's name, and the list's rows reverse in right-to-left text. - Announcements: "2 files added" is announced politely; refusals are announced as an alert.
- Dragging: the zone lights up only for files (not dragged text or links) and says "Drop to add".
- Touch: the button's hit area is at least 44px on touch screens.
- Contrast: the prompt and hint keep 4.5:1 in light and dark modes.
- All built-in text is in
labels.
ThemingLink to "Theming"
Tokens: --cy-file-drop-radius, --cy-file-drop-active-background, --cy-file-drop-overlay-background and --cy-file-drop-file-background (a chosen file's row).
RelatedLink to "Related"
These examples run Cynosure 0.5.0 (commit 50ce30b), the version on npm.