figma guide

Designing file upload and drag-drop UI in Figma: patterns, states, and handoff

Design file upload zones, drag-drop states, progress bars, and error handling in Figma with size limits, multi-file queues, and Dev Mode specs for forms.

Published
Updated
Jun 13, 2026
Read time
8 min
Level
Beginner

Quick answer

File upload UI in Figma covers the drop zone, file queue, progress, and outcomes—empty, dragging, uploading, success, and error. Build an UploadZone component with variants for state=empty | drag-over | uploading | success | error, layout=compact | full, and multiple=true | false. Pair with forms, progress indicators, and inline alerts. Document accepted file types, max size, max count, virus scan / processing delays, and retry behavior in Dev Mode. Start from the Figma guides hub for component patterns.


Who this is for

  • Product designers shipping onboarding, settings, CMS, and attachment flows.
  • Design system teams standardizing upload zones that were one-off dashed rectangles in every file.
  • Engineers implementing drag-drop APIs, chunked uploads, and accessible file inputs.

Upload patterns compared

PatternInteractionBest forAvoid when
Full drop zoneLarge dashed area; click or dragFirst-time upload, onboardingInline edit in dense tables
Compact button”Upload file” opens native pickerSettings, side panelsMarketing hero uploads needing guidance
Inline rowAttach icon in form footerSupport tickets, commentsLarge video files
Avatar / image cropCircle drop + crop modalProfile photosGeneric documents
Replace fileShows current file + “Replace”Config, logo uploadMulti-file galleries
Paste from clipboard⌘V image pasteDesign tools, chatRequired for all flows

Verdict: use a full drop zone when upload is the primary action; use compact + queue list when upload is secondary inside a longer form.


Component anatomy

PartPurposeSpec tip
Drop zone containerHit target for drag + clickMin height 120–160px full; 40px compact
IconUpload cloud or document24–32px; muted default
Headline”Drag files here”Sentence case
SubcopyTypes, size limit”PDF, PNG up to 10 MB”
Browse buttonOpens file pickerSecondary button style
Hidden inputNative <input type="file">Document accept attribute
File queueList of selected filesBelow zone or inside modal
Progress rowPer-file bar + %Link to progress pattern
Remove controlX per rowAvailable until upload completes
Success / errorIcon + message per fileRetry on error
UploadZone
├── Variant: state=empty | drag-over | uploading | success | error
├── Variant: layout=full | compact
├── Property: multiple=true | false
├── Layer: Container (dashed border, radius md, padding 24–32px)
│   ├── Icon
│   ├── Headline + subcopy
│   └── Browse button
├── Layer: FileQueue (vertical auto layout, gap 8px)
│   └── FileRow × N
│       ├── File icon / thumbnail
│       ├── Name + size (truncate)
│       ├── Progress bar
│       ├── Status (uploading | done | error)
│       └── Remove button
└── Layer: Global error alert (optional)

Use auto layout so the queue expands without manual nudging. Thumbnails: 40×40 for images; generic doc icon for PDFs.


Drop zone states

StateVisualInteraction
EmptyDashed border; muted iconClick or drag files
Drag overSolid border; brand tint backgrounddrag-over highlight
UploadingDisabled drop; progress in queueNo new files unless allowed
SuccessCheckmark; optional collapseShow link or preview
ErrorRed border or inline alertRetry + clear
DisabledMuted; no pointerQuota reached, permissions

Reuse interactive components for hover on the browse button—not always on the full zone (avoid misleading click affordance on non-button areas unless the whole zone is clickable).


File row and progress

ElementSpecHandoff
File nameTruncate middle (report…final.pdf)Full name in title tooltip
File sizeHuman readable (2.4 MB)Bytes for logic
Progress barDeterminate 0–100%Indeterminate if unknown
CancelStops in-flight uploadDistinct from Remove after complete
RetryOn failed row onlyMax attempts?
ThumbnailImage preview when type is imageObject-fit cover

Align progress bar height with your progress indicator tokens—typically 4–8px for inline rows.


Constraints to document

ConstraintExample copyEngineering note
File types.pdf, .png, .jpgaccept + server validation
Max size10 MB per file10 * 1024 * 1024 bytes
Max count5 filesDisable drop when queue full
Min dimensions800×600 for bannersImage validation after upload
Aspect ratio1:1 for avatarsPair with crop modal
Total quota100 MB per userEmpty state when full

Never show “Upload any file” in UI if the backend rejects types—match marketing copy to real rules.


Image upload and crop flow

StepUINotes
1User selects imageDrop zone or avatar click
2Client previewThumbnail in queue
3Crop modal1:1 for avatars; free for banners
4Upload progressPer-file bar
5SuccessUpdated avatar or card image

Document min crop size, output format (JPEG 85%), and max output dimensions in the modal handoff. Use a modal with primary Save and secondary Cancel.


Multi-file and queue behavior

BehaviorOption AOption B
Upload startAuto on dropUser clicks “Upload all”
Parallel uploads3 at a timeOne at a time
FailureOne error does not block othersStop entire batch
OrderPreserve pick orderSort by name
Remove after successHide rowKeep with checkmark

Pick one column per product and document in the component description—do not leave engineering to guess.


Pairing with other patterns

NeedPatternLink
Form submitUpload inside formDisable submit until required file present
Loading pageSkeleton while processingVirus scan, transcoding
Success feedbackToast”3 files uploaded”
Global failureInline alertNetwork offline
No files yetEmpty stateDocument library before upload
Confirm deleteModalRemove published asset

Accessibility checklist

RequirementImplementation
Native inputReal <input type="file"> or equivalent
Labelaria-label or visible label tied to input
KeyboardBrowse button focusable; Enter opens picker
Drag-dropNot keyboard-only path—always offer button
Progressaria-valuenow on progress bar
Errorsrole="alert" or aria-live="polite"
InstructionsDo not rely on color alone for errors

Test with screen reader: announce file name, size, and error reason per row.


Prototyping limits

Figma cannot upload real files. For demos:

  1. Build frames: empty, drag-over, queue uploading, one error, success.
  2. Wire Browse → queue with placeholder rows (swap component variants).
  3. Note chunked upload and retry in sticky comments.

Use sections for onboarding vs settings contexts.


Handoff to engineering

DeliverableWhere it lives
accept MIME / extensionsComponent description
maxFileSizeBytesToken or spec table
maxFilesNumber
upload URL / methodPOST multipart—link API doc
HeadersAuth, Content-Type
Progress eventsPer-file onProgress
Cancel / abortAbortController per row
Preview rulesThumbnail for images only
Post-upload processingPolling vs webhook
Error codesMap to user-facing strings

Include upload in your Dev Mode handoff checklist. Export icons with production-ready assets where needed.


Real-world examples

Support ticket attachment

Compact upload below form message field. Max 3 files, 5 MB each. Queue with remove before submit. Success: files listed in submitted ticket view.

Company logo in settings

Single file, replace pattern. Shows current logo thumbnail. SVG + PNG accepted. Inline alert on wrong type.

Bulk import (CSV)

Full drop zone with template download link. Processing progress on full page after upload. Table preview of parsed rows with error highlights.


Common mistakes

MistakeConsequenceFix
Clickable zone with no keyboard pathFails a11yAlways show Browse button
No file type copyUsers upload wrong formatsList types in subcopy
Progress only at page levelUsers cannot tell which file failedPer-file rows
No remove before uploadStuck with wrong fileX on each queue row
Drag-over same as error redConfusing feedbackBrand tint for drag-over
Giant zone in every formWastes spaceCompact variant in forms
Success with no previewUsers unsure it workedThumbnail or filename check
Missing max sizeSupport burdenShow limit before failure

FAQ

Drag-drop only vs button only?

Always provide both. Drag-drop is faster for desktop; Browse is required for keyboard, mobile, and screen readers.

Upload before or after form submit?

Immediate upload for large files (shows progress early). On submit for short forms with small attachments—document which flows use which.

Show upload in tables?

Rare—prefer bulk import page. Per-row replace is OK for single-document records (invoice PDF).

Cloud picker (Google Drive, Dropbox)?

Optional secondary action “Import from…” below the zone—separate component variant; same queue list after selection.


Bottom line

Treat file upload as a state machine: empty, drag-over, queue, progress, success, and error—with explicit limits and retry rules. Document accept, sizes, count, and API behavior in Dev Mode. Continue with forms, progress indicators, empty states, and the tutorials hub.

Share on X

§ Keep reading

Related guides.