Docs
UploadCard

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…
  • Collecting files from the user (images, PDFs, spreadsheets) in a form.
  • When you need per-file visual progress feedback.
  • For drag-and-drop (with a button fallback).
  • For a single trivial file (logo, avatar) — a styled <input type="file"> may be enough.
  • For streaming uploads (large chunks). This component uses Promise.all over XHR — ideal for medium-sized files.

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 UploadCard is used inside a Form (the imperative ref is not forwarded). For uploads with progress, use the component standalone and control the files via onChange.
  • Don't omit acceptLabel in user-facing UI — people need to know which file types are accepted before they try to upload one.
  • accept is 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.