UploadCard
File upload card with drag-and-drop, multiple-file support, MIME-type filtering, and real-time progress reporting.
When to use
| ✅ Use when… | 🚫 Avoid when… |
|---|---|
|
|
Basic example
PNG, JPEG, GIF, PDF
Arraste e solte aqui
ou
With submit via ref
import { Flex } from '@apollion-dsi/core/containers/flex';
import { useNotification } from '@apollion-dsi/core/containers/notification';
import { Button } from '@apollion-dsi/core/elements/button';
import { UploadCard, UploadCardRef } from '@apollion-dsi/core/form/upload-card';
function Example() {
const uploadRef = useRef<UploadCardRef>(null);
const { showNotification } = useNotification();
const submit = async () => {
if (uploadRef.current?.files.length) {
const responses = await uploadRef.current.submit({
endpoint: 'https://httpbin.org/post',
});
console.log({ responses });
} else {
showNotification({ variant: 'danger', message: 'WHERE ARE THE FILES?' });
}
};
return (
<Flex gap="small">
<UploadCard
accept={['image/*', 'video/*', 'application/pdf']}
acceptLabel="PNG, JPEG, GIF, PDF"
ref={uploadRef}
onChange={(value) => console.log({ value })}
onUnsupportedFile={() => showNotification({ variant: 'danger', message: 'Unsupported file!' })}
/>
<Flex flexDirection="row" wrap="wrap" gap="small">
<Button size="small" text="Submit" onClick={submit} />
<Button size="small" text="Reset" onClick={() => uploadRef.current?.removeAll()} />
</Flex>
</Flex>
);
}compact variant
Reduced version, ideal for dense forms where the default card would take up too much vertical space.
<UploadCard
compact
accept={['image/*', 'application/pdf']}
acceptLabel="PNG, JPEG, PDF"
onChange={(value) => console.log(value)}
/>useFileControl hook
Use when you need to know which files changed between load and save — useful in form editing where the backend expects two events (POST for the new ones, DELETE for the removed ones).
const { onFilesChange, addedFiles, removedFiles, clear } = useFileControl();
<UploadCard onChange={onFilesChange} ... />;
await syncFiles({ added: addedFiles, removed: removedFiles });
clear('addedFiles');
clear('removedFiles');Limitations
- The upload progress feature is not available when the
UploadCardis used inside aForm(the imperative ref is not forwarded). For uploads with progress, use the component standalone and control the files viaonChange. - Don't omit
acceptLabelin user-facing UI — people need to know which file types are accepted before they try to upload one. acceptis a client-side hint, not a security boundary — always revalidate the MIME type on the backend.
Properties
Prop | Type | Default | Description |
|---|---|---|---|
accept * | string[] | — | Accepted file types. Accepts extensions (`'.png'`) or MIME types
(`'image/*'`). Rejected items trigger `onUnsupportedFile`.
@see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept |
acceptLabel | string | — | Label for the accepted types (e.g. `"PNG, JPEG, PDF"`) shown on the card. |
buttonText | string | 'Enviar arquivos' | Text of the selection button. |
className | string | — | — |
compact | boolean | false | Compact visual variant — single row instead of the large card. |
customButton | ((p: CustomButtonProps) => ReactNode) | — | Replaces the default button with a custom one. Receives utilities to
open the dialog, read the current files, and the submit state. |
disabled | boolean | — | — |
initialFiles | File | File[] | — | Files to populate on mount (useful when editing forms). |
maxSize | number | 15728640 // 15 MB | Maximum size per file, in bytes. |
name | string | — | Name of the `<input type="file">` (required in native forms). |
onChange | ((value: UploadCardOnChangeValue) => void) | — | Callback fired on every change (ADD, REMOVE, UPDATE,...). |
onUnsupportedFile | ((f: File) => void) | — | Callback for files rejected by `accept` (not by `maxSize`). |
readOnly | boolean | — | — |
singleFile | boolean | false | Restricts to a single file (drag/drop and dialog). |
style | CSSProperties | — | — |
uploadConfig | UploadFileRequestConfig | — | Upload configuration — required to use `ref.submit()`. |
In addition to the props above, every component accepts the layout props (spacing, color, flex/grid, sizing, border) — not repeated here.
See also
- Storybook story: Components / UploadCard
- Tracking helper:
useFileControl.