File Upload
File Upload lets people attach a file, and reports progress, success and failure along the way.
Preview
The surface that takes a file. Default invites the first tap. Bind State to the real request, never decorative: on iOS fileImporter, on Android GetContent.
Tap it. Default to Active to Uploading to Upload, the four states in order. Tap again to restart. Inside the box: a 24 icon, a 292 text column and, while uploading, a 292 by 4 track, stacked 12 apart with 4 between the two lines. Height is fixed at 180, so nothing moves as the state changes.
State
Six states, one 340 by 180 box. What changes: the fill, the edge, the icon and which of the two lines carries the message.
In order: Default, white with a grey dash. Active, brand/lighter with a brand edge, press and drag-over. Uploading adds the track, filled to 191 of 292. Upload swaps the icon for the file type mark, filename on the primary line. Error recolours the edge, icon and supporting line, which carries the reason. Disabled has no edge. The four strings never change, only their colour. The dash is 5 on 3, an SVG rect: a CSS dashed border cannot set its pattern and Chrome draws roughly 3 on 3. The Upload mark is Adobe Acrobat in the file, a neutral tile here.
Properties
One axis and two text fields. No size, no layout, no boolean: the box is the same on every state.
Disabled is the only state without an edge. It reads as a surface, not a target. Error is the only one that recolours the supporting line.
Tokens
Every value the component reads, resolved through its aliases to the Foundations primitive.
state/information/base-500 aliases colors/blue/500 in both modes, so it does not lift in dark the way brand/base does. A dark Active card carries a #2B7FFF edge around a #155DFC label. The label is the half you have to read. Geometry runs on dimensions/radius/3xl 32, dimensions/spacing/6 24, dimensions/spacing/3 12 and dimensions/border/1.
Guidelines
Put the reason on the supporting line. The state has a place for the message, so use it instead of a toast that leaves.
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.
Uploading, Upload and Error are answers from the server. Wire State to the real request: a card that says Uploading while nothing is in flight is worse than no state at all.