Skip to content

File Upload

File Upload is where a person adds a photo or a document. After that it reports progress, success and failure.

On this page
  1. Preview
  2. States
  3. Properties
  4. Tokens
  5. iOS and Material 3
  6. Guidelines

Preview

A drop zone for photos and documents: Default invites the first tap and offers camera, photo library and files as sources, and Active marks the press or drag-over. Press it to run the whole cycle.

File Upload, press to run the cycleZone 361 x 212, row 361 x 72, radius 16, dash 6 on 4 at 1
Upload a filePNG, JPG or PDF, up to 10 MBCameraPhotosFilesbrief.pdf0 of 2.4 MB · 0%0.9 of 2.4 MB · 38%1.6 of 2.4 MB · 65%2.1 of 2.4 MB · 88%2.4 of 2.4 MB · 100%2.4 MB · Uploaded

The cycle runs Default, Active, Uploading, Upload in that order, and a press during the run starts over.

The set draws two shapes: the drop zone stays until a file is chosen, then the component shrinks to a file row, so a finished upload takes less room than the invitation to add one. The progress bar, the file name and a round action, Cancel, Remove or Retry, live in that row.

The supporting text and the meta line are fg/soft-500, #8E8E93, which measures 3.26 to 1 on white and 2.99 to 1 on the bg/weak-50 zone, under the 4.5 to 1 that WCAG asks of small text.

In code, make the whole zone one button with a visible focus ring that opens the system picker. The zone is 361 by 212, far above the minimum touch target, while the source pills and the round actions are 36 and need a larger hit area.

Source: the File Upload set of the Appetite UI Figma file, read on October 2, 2026.

Which states does File Upload have?

Six states in two shapes: Default, Active and Disabled are the drop zone, and Uploading, Upload and Error are the file row. The rows differ only in what the second line says and which action sits at the end.

State Default, Active, Disabled, Uploading, Upload, Errorzone 361 x 212 padding 24, row 361 x 72 padding 16 8 16 16

Default

Upload a filePNG, JPG or PDF, up to 10 MBCameraPhotosFilesbrief.pdf0 of 2.4 MB · 0%0.9 of 2.4 MB · 38%1.6 of 2.4 MB · 65%2.1 of 2.4 MB · 88%2.4 of 2.4 MB · 100%2.4 MB · Uploaded

Active

Upload a filePNG, JPG or PDF, up to 10 MBCameraPhotosFiles

Disabled

Upload a filePNG, JPG or PDF, up to 10 MBCameraPhotosFiles

Uploading

brief.pdf1.4 of 2.4 MB · 60%

Upload

brief.pdf2.4 MB · Uploaded

Error

brief.pdfOver 10 MB. Try a smaller file.

The three zone states share one shape and change the paint. Active fills the zone with brand at 10 percent alpha, draws the dashed edge in brand and turns the featured circle brand with a white icon.

Disabled keeps the dashed edge on border/soft-100 and moves every ink to fg/disabled-400.

The row states share a second shape. Uploading shows the file name, a meta line with the amount sent and a 4 high progress bar.

Upload swaps the bar for a green check and the word Uploaded, and Remove replaces Cancel. Error moves the stroke, the file tile and the meta line to the error colors, keeps the name, and offers Retry.

Which properties does File Upload have?

One variant axis and three text properties. The zone reads Label and Supporting Text, the row reads File Name.

Properties, property, type, default
PropertyTypeDefault
StateDefault, Active, Uploading, Error, Disabled, UploadDefault
LabelText, on the drop zoneUpload a file
Supporting TextText, on the drop zonePNG, JPG or PDF, up to 10 MB
File NameText, on the file rowbrief.pdf
State, shape, fill, edge, leading and meta
StateShapeFillEdgeLeading and meta
DefaultZone 361 x 212bg/weak-50dashed border/sub-200cloud-upload in brand/base on a white circle, three source pills
ActiveZone 361 x 212brand/alpha-10dashed brand/basethe same, on a brand circle with a white icon
DisabledZone 361 x 212bg/weak-50dashed border/soft-100every ink fg/disabled-400
UploadingRow 361 x 72bg/white-0solid border/soft-100file tile, name, amount sent, progress bar, Cancel
UploadRow 361 x 72bg/white-0solid border/soft-100file tile, name, green check and Uploaded, Remove
ErrorRow 361 x 72bg/white-0solid state/error/light-200error tile, name, the reason in state/error/base-500, Retry

The meta line, the source pills and the actions are layers inside the set and carry no property; the pills are Button instances at Neutral, Outline, sm. Change the meta text on the instance, and show or hide a source by editing the Sources row.

Tokens

Every value the component reads, resolved through its aliases in Light and Dark.

Tokens, token, light, dark, applied to
TokenLightDarkApplied to
bg/weak-50#F4F5F5#242427Zone fill and the file tile
bg/white-0#FFFFFF#0E0E0FRow fill, the featured circle at rest and the source pills
border/sub-200#D1D1D6#48484ADashed edge at rest
border/soft-100#E9E9EA#2F2F31Row stroke, pill stroke and the Disabled dashed edge
brand/base#155DFC#2B7FFFActive edge and circle, the icon at rest, the progress fill
brand/alpha-10#2B7FFF at 10%#2B7FFF at 10%Active fill
bg/soft-100#E9E9EA#48484AProgress track and the Disabled circle
fg/strong-950#0E0E0F#FFFFFFLabel and file name
fg/soft-500#8E8E93#AEAEB2Supporting text and meta
text/sub-700#48484A#C7C7CCPill labels
fg/sub-700#48484A#C7C7CCPill icons, tile icon, action icon
text/on-color/strong#FFFFFF#FFFFFFIcon on the Active circle
fg/disabled-400#AEAEB2#8E8E93Every ink on Disabled
state/success/base-500#22C55E#16A34ACheck beside Uploaded
state/error/light-200#FFC9C9#FB2C36 at 24%Error stroke
state/error/lighter-50#FEF2F2#FB2C36 at 16%Error tile
state/error/base-500#FB2C36#FB2C36Error icon and reason
dropShadow/xseffecteffectFeatured circle at rest

The edge is 1 wide in every state and drawn inside the frame, so it never changes the size.

Source: the Color Tokens collection of the Appetite UI Figma file, read on October 2, 2026.

How does File Upload differ on iOS and Material 3?

File Upload has no counterpart in the iOS or Material 3 pages of the file, because both platforms hand file selection to a system picker. Build the surface here and let it open the picker.

File Upload against its iOS and Material 3 counterparts, component, iOS, Material 3, difference
Appetite UIiOS counterpartMaterial 3 counterpartWhat differs
File UploadNone in the kit. SwiftUI offers PhotosPicker and fileImporterNone in the kit. Android offers the Photo Picker and GetContentThe system pickers draw the chooser. File Upload draws the surface that opens it and the progress after it, and the three sources map onto the pickers.

The source pills and the round actions are 36 high, under the minimum touch target of 44 pt on iOS and 48 dp on Android set by platform/min-touch-target, so add hit area in code. The whole drop zone is the larger target for the first tap.

See Platform Bridge, iOS and Material 3 for how the same component adopts each platform.

Guidelines

Do

Put the reason on the meta line. The state has a place for the message, so use it instead of a toast that leaves.

report.pdfOver 10 MB. Try a smaller file.

Don't

Do not leave the supporting line empty. What you accept and how big it can be is the one thing the user needs before they choose.

Upload a fileCameraPhotosFiles

Uploading, Upload and Error are answers from the server, so wire State to the real request. A row that says Uploading while nothing is in flight is worse than no state at all.

Tell assistive technology what happened. Announce Uploading and Upload in a polite live region and Error in an assertive one with the reason, and keep the progress amount as text, which the meta line already is.