Components · Forms & selection
File input
A dashed drop zone that doubles as a click target, with a list of selected files and per-file upload progress. Hover and drag-over tint the zone toward the brand; rejected files surface in the danger surface inline.
Preview
Light
upload
Drop files here or browse
PNG, JPG or PDF up to 10MB
description
brand-guidelines.pdf
2.4 MB
error
hero-render.psd
Too large
Dark
upload
Drop files here or browse
PNG, JPG or PDF up to 10MB
description
brand-guidelines.pdf
2.4 MB
error
hero-render.psd
Too large
Accessibility
upload
Drop files here or browse
PNG, JPG or PDF up to 10MB
description
brand-guidelines.pdf
2.4 MB
error
hero-render.psd
Too large
Spec
Values and token references straight from the Zetta spec.
file-input
- backgroundColor
- {colors.surface-card}
- borderColor
- {colors.border-strong}
- borderWidth
- 1px
- borderStyle
- dashed
- borderRadius
- {rounded.base}
- textColor
- {colors.muted}
- fontFamily
- Geist
- fontSize
- 14px
- fontWeight
- 400
- lineHeight
- 1.6
- padding
- {spacing.md}
- display
- flex
- flexDirection
- column
- alignItems
- center
- justifyContent
- center
- gap
- {spacing.sm}
- minHeight
- 96px
- cursor
- pointer
- iconSize
- 20px
- iconColor
- {colors.muted}
file-input-hover
- borderColor
- {colors.border-focus}
- backgroundColor
- {colors.brand-bg}
file-input-focus
- outline
- 2px solid {colors.border-focus}
- outlineOffset
- 2px
- borderColor
- {colors.border-focus}
file-input-drag-over
- borderColor
- {colors.brand}
- backgroundColor
- {colors.brand-bg}
- iconColor
- {colors.brand}
file-input-disabled
- backgroundColor
- {colors.disabled-bg}
- borderColor
- {colors.disabled-border}
- textColor
- {colors.disabled-text}
- cursor
- not-allowed
file-input-error
- borderColor
- {colors.danger}
file-input-file-list
- display
- flex
- flexDirection
- column
- gap
- {spacing.xs}
- marginTop
- {spacing.sm}
file-input-file-item
- display
- flex
- alignItems
- center
- gap
- {spacing.sm}
- backgroundColor
- {colors.surface-secondary}
- borderRadius
- {rounded.base}
- paddingX
- 12px
- paddingY
- 8px
- fontFamily
- Geist
- fontSize
- 13px
- fontWeight
- 400
- textColor
- {colors.ink}
- iconSize
- 16px
- iconColor
- {colors.muted}
file-input-file-item-error
- backgroundColor
- {colors.danger-bg}
- textColor
- {colors.danger-text}
- iconColor
- {colors.danger-text}
file-input-progress
- height
- 4px
- borderRadius
- {rounded.full}
- trackColor
- {colors.surface-muted}
- fillColor
- {colors.brand}
- marginTop
- 4px
Build with the skill
No package to install — hand this to your AI to generate the file input in your stack.
Implement the Zetta "File input" component in this project's stack using the zetta-design-md skill.
- Apply the `file-input` spec from the skill (variants: default, drag-over, error, disabled).
- Use this project's own component conventions and framework idioms.
- Reference the Zetta design tokens (CSS variables) for every color, radius, and shadow — never hardcode values.
- Implement all states (hover, focus, active, disabled, and invalid where applicable) with a visible 2px focus ring.
- Honor the Zetta guardrails (brand never shifts hue, shadows for overlays only, etc.) and verify in Light, Dark, and Accessibility. Anatomy & rules
- Min-height 96px, 1px dashed border, base radius, centred icon + label in
muted. Hover and drag-over usebrand-bg; the drag-over border and icon go fullbrand. - File rows sit on
surface-secondary; errored rows use the danger surface. Progress is a 4px full-radius track filling withbrand.
Accessibility
- Back the zone with a real
<input type="file">so it is keyboard reachable and announces as a file picker. Drag-and-drop is an enhancement, never the only path. Announce upload progress and errors via live regions.