FixNeeds Refinement
Upload File Component link

A file-upload field with a tappable upload affordance, file-name display, and progress/error states.

Property + token cleanup needed
Fix the boderborder token typo (library-wide). Normalize hasLabel to true/false. Split state="Uploaded with thumbnail" into state=uploaded + hasThumbnail: Bool. Rename "Upload error"error (remove space). Adopt a Figma Slot for the thumbnail image. Add disabled state.
In Context

Contexts are illustrative. Final screens will reference actual GCash patterns. Upload File appears in forms requiring document proof (KYC, insurance claims, verification).

Upload Docs Attach file / photo ID_proof.jpg Submit
Live Preview
Attach file / photoAccepted format: JPEG, PNG, or PDF, Up to 3 MB
Properties
state
hasLabel
DS Health
Reusable
Pass
Used in KYC flows, insurance claims, profile setup — anywhere a user uploads a document or photo. Five states cover the full upload lifecycle.
Self-contained
Warn
Carries its own bg, border, padding, radius. Progress bar relies on an external Lottie animation — must be bundled with the native package as an asset dependency. Thumbnail placeholder uses a hardcoded hex with baked opacity instead of a token. C3
Consistent
Warn
Three property-naming issues: hasLabel uses yes/no, state="Upload error" contains a space, and "Uploaded with thumbnail" is really an orthogonal boolean, not a state. Also the boder typo in every border token. C2 C3
Composable
Warn
Thumbnail is a 52×52 hardcoded placeholder block (same icon-placeholder pattern we've flagged in Chip, Tab Item, List Item Asset) — should be a Figma Slot so product teams can drop in any preview image. C6
Behavior
State iOS Android Figma Property Notes
Default Yes Yes state=Default Empty input with paperclip + "Attach file / photo" label
Uploading Yes Yes state=Uploading Shows file name + Lottie progress bar + percentage
Uploaded Yes Yes state=Uploaded File name + trailing trash icon to remove
Uploaded with thumbnail Yes Yes state=Uploaded with thumbnail 52×52 image preview + truncated file name + trash. Should be orthogonal hasThumbnail prop.
Upload error Yes Yes state=Upload error Red 2px border + red subtext ("Maximum file size: 20MB")
Disabled / Pressed / Focused N/A N/A Not defined. Engineers must improvise. C5
Open Issues
  • Property naming issues. hasLabel uses yes/no instead of true/false; state="Upload error" contains a space; state="Uploaded with thumbnail" mixes two orthogonal dimensions (state + thumbnail presence). C2 · Variant & Property Naming
  • Token typo — boder. Every border token is misspelled: main/upload-file/color/default/boder, main/upload-file/color/error/boder. Rename across the whole collection. C3 · Token Coverage
  • Thumbnail color hardcoded. Uses #0057E4 with opacity: 5% baked in instead of a token. C3 · Token Coverage
  • No disabled / pressed / focused states. Forms need a disabled variant for read-only views; pressed and focused are expected interaction affordances. C5 · Interaction State Coverage
  • Thumbnail is a placeholder. 52×52 gray block instead of a swappable image slot. Should be a Figma Slot that accepts a real image instance. C6 · Asset & Icon Quality
  • Lottie dependency. Progress bar requires the Lottie animation (0a1cb540-b53a-4e28-afa5-8aa5ca7ebaa1) to be bundled with the native package. Document as a required asset. C6 · Asset & Icon Quality
  • Code Connect mappings not registered. Blocked until state/property restructure and token rename land. C7 · Code Connect Linkability
Design Recommendations
  • Restructure the state property :
    state: default / uploading / uploaded / error (4 values, clean enums)
    hasThumbnail: Bool (orthogonal — can combine with uploaded)
    hasLabel: Bool (true/false)
    disabled: Bool (new)
    Collapses 10 variants into 4 states × 2 hasLabel × 2 hasThumbnail × 2 disabled = 32 prop combinations with no invalid states. Property
  • Fix the boder typo across the token collection. Rename both default/boder and error/boder. Library-wide change — affects every variant. Token
  • Tokenize the thumbnail placeholder — replace hardcoded #0057E4 @ 5% with main/upload-file/color/default/thumbnail-bg. Token
  • Adopt a Figma Slot for the thumbnail — swappable preview image. Maps to @ViewBuilder / @Composable slot for Code Connect. Slot
  • Reuse Labeled Field for the label + subtext scaffolding. Today Upload File reimplements the label-above + subtext-below pattern that Labeled Field already ships. Making Upload File an input slot inside Labeled Field reduces duplication. Composition
  • Document the Lottie dependency — Progress bar is a Lottie animation. Native packages must bundle the animation JSON. Consider replacing with a native progress bar for a lighter dependency. Docs
Styles
Default — empty state
DES DEV

Empty state with paperclip + "Attach file / photo" placeholder text. 2px border, white bg. Subtext below lists accepted formats.

Properties
state
hasLabel
hasThumbnail
disabled
Properties
state Default
Variant Default — empty state
hasLabel no
hasThumbnail false
disabled false
Colors
Bg #FFFFFF
Border #D7E0EF
Text #0A2757
Placeholder #90A8D0
Layout
Field height 48px
Padding H 12px
Border radius radius/radius-2 (6px)
Upload icon 20 × 20
Typography
Label style Primary/Label/Light/Small
Label font Proxima Soft Semibold · 14 / 14
Colors by State
Role Token TokenValue
Default bg main/upload-file/color/default/bg #FFFFFF
border main/upload-file/color/default/boder typo #E5EBF4
leading icon main/upload-file/color/default/icon-leading #6780A9
trailing icon main/upload-file/color/default/icon-trailing #005CE5
label main/upload-file/color/default/label #0A2757
file name main/upload-file/color/default/label-name #005CE5
progress label main/upload-file/color/default/progress-label #0A2757
thumbnail bg — (hardcoded #0057E4 @ 5%) not tokenized
Error bg main/upload-file/color/error/bg #FFFFFF
border main/upload-file/color/error/boder typo #D61B2C
leading icon main/upload-file/color/error/icon-leading #6780A9
label main/upload-file/color/error/label #0A2757
file name main/upload-file/color/error/label-name #005CE5
error subtext main/subtext-message/error/label #D61B2C
Subtext default label main/subtext-message/primary/label #6780A9
Uploading — Lottie progress
DES DEV

Shows file name + 5px-tall Lottie progress bar + percentage. Height grows to 91px to accommodate the progress row.

Properties
state
hasLabel
hasThumbnail
disabled
Properties
state Uploading
Variant Uploading — Lottie progress
hasLabel no
hasThumbnail false
disabled false
Colors
Bg #FFFFFF
Border #D7E0EF
Text #0A2757
Placeholder #90A8D0
Layout
Field height 48px
Padding H 12px
Border radius radius/radius-2 (6px)
Upload icon 20 × 20
Typography
Label style Primary/Label/Light/Small
Label font Proxima Soft Semibold · 14 / 14
Layout
Role Token Value
Container width 304px
Input height (default/uploaded/error) 72px
Input height (uploading) 91px (adds progress row)
Border width 2px
Corner radius radius/radius-2 6px
Horizontal padding 16px (12L / 16R for thumbnail)
Vertical padding 24px
Icon → name gap space/space-4 4px
Thumbnail size 52 × 52
Thumbnail → name gap space/space-8 8px
Label → input gap space/space-8 8px
Input → subtext gap space/space-8 8px
Progress bar height 5px
Progress bar width 250px
Leading / trailing icon size 24 × 24
Uploaded — file name + trash
DES DEV

File name (<code>GCash_File.png</code>) + trailing trash icon for removal.

Properties
state
hasLabel
hasThumbnail
disabled
Properties
state Uploaded
Variant Uploaded — file name + trash
hasLabel no
hasThumbnail false
disabled false
Colors
Bg #FFFFFF
Border #D7E0EF
Text #0A2757
Placeholder #90A8D0
Layout
Field height 48px
Padding H 12px
Border radius radius/radius-2 (6px)
Upload icon 20 × 20
Typography
Label style Primary/Label/Light/Small
Label font Proxima Soft Semibold · 14 / 14
Typography
Role Token Spec
Label Primary/Label/Light/Small Proxima Soft Semibold · 14 / 14 · +0.25
File name / placeholder Primary/Label/Light/Large Proxima Soft Semibold · 18 / 18 · +0.25
Subtext Secondary/Bold/Caption BarkAda Semibold · 12 / 18
Progress percentage Secondary/Bold/Small Caption BarkAda Semibold · 10 / 15
Uploaded with thumbnail — preview + name
DES DEV

52×52 thumbnail preview + truncated file name (<code>New_GCash_Fi….jpeg</code>) + trash. Recommended to split into <code>state=uploaded</code> + <code>hasThumbnail: true</code>.

Properties
state
hasLabel
hasThumbnail
disabled
Properties
state Uploaded with thumbnail
Variant Uploaded with thumbnail — preview + name
hasLabel no
hasThumbnail true
disabled false
Colors
Bg #FFFFFF
Border #D7E0EF
Text #0A2757
Placeholder #90A8D0
Layout
Field height 48px
Padding H 12px
Border radius radius/radius-2 (6px)
Upload icon 20 × 20
Typography
Label style Primary/Label/Light/Small
Label font Proxima Soft Semibold · 14 / 14
Upload error — red border + error subtext
DES DEV

Red 2px border + red error subtext ("Maximum file size: 20MB").

Properties
state
hasLabel
hasThumbnail
disabled
Properties
state Error
Variant Upload error — red border + error subtext
hasLabel no
hasThumbnail false
disabled false
Colors
Bg #FFFFFF
Border #D61B2C
Text #0A2757
Placeholder #90A8D0
Layout
Field height 48px
Padding H 12px
Border radius radius/radius-2 (6px)
Upload icon 20 × 20
Typography
Label style Primary/Label/Light/Small
Label font Proxima Soft Semibold · 14 / 14
Installation Planned API

iOS — Swift Package Manager

// In Xcode: File → Add Package Dependencies
"https://github.com/AY-Org/eb-ds-ios"

// Requires: lottie-ios for progress animation
"https://github.com/airbnb/lottie-ios"

Android — Gradle (Kotlin DSL)

dependencies {
    implementation("com.eastblue.ds:upload-file:1.0.0")
    // Requires: lottie-compose for progress animation
    implementation("com.airbnb.android:lottie-compose:6.4.0")
}
Property Mapping
Figma PropertySwiftUICompose
state=Default/Uploading/Uploaded/Upload error state: EBUploadState state: .default / .uploading / .uploaded / .error
state=Uploaded with thumbnail state=uploaded + hasThumbnail .hasThumbnail(true)
hasLabel=yes/no label: String? label: String?
fileName: String? fileName: String?
progress: Double progress: Double (0.0–1.0)
thumbnail placeholder Figma Slot → ViewBuilder @ViewBuilder thumbnail
disabled: Bool .disabled(true)
onSelect / onRemove onSelect / onRemove
SwiftUI
ios/Components/UploadFile/EBUploadFile.swift
Jetpack Compose
android/components/uploadfile/EBUploadFile.kt
Usage Snippets Planned API
Usage
// Default — empty state
EBUploadFile(label: "Proof of ID", onSelect: { url in
    // handle picked file
})

// Uploading
EBUploadFile(fileName: "GCash_File.png", progress: 0.2)
    .ebState(.uploading)

// Uploaded with thumbnail (Figma Slot)
EBUploadFile(fileName: "ID_proof.jpg", onRemove: { ... }) {
    AsyncImage(url: imageURL)
        .aspectRatio(contentMode: .fill)
        .clipShape(RoundedRectangle(cornerRadius: 4))
}
.ebState(.uploaded)

// Error
EBUploadFile(label: "Upload receipt",
    errorMessage: "Maximum file size: 20MB")
    .ebState(.error)
// Default — empty state
EBUploadFile(
    label = "Proof of ID",
    onSelect = { uri -> /* handle picked file */ }
)

// Uploading
EBUploadFile(
    state = EBUploadState.Uploading,
    fileName = "GCash_File.png",
    progress = 0.2f
)

// Uploaded with thumbnail (Figma Slot)
EBUploadFile(
    state = EBUploadState.Uploaded,
    fileName = "ID_proof.jpg",
    onRemove = { /* ... */ }
) {
    AsyncImage(
        model = imageUrl,
        contentDescription = null,
        modifier = Modifier.clip(RoundedCornerShape(4.dp))
    )
}

// Error
EBUploadFile(
    state = EBUploadState.Error,
    label = "Upload receipt",
    errorMessage = "Maximum file size: 20MB"
)
Accessibility
RequirementiOSAndroid
Role .accessibilityAddTraits(.isButton) when empty; announce as "Upload" when actionable Role.Button in semantics
File picked announcement Announce file name after selection via .accessibilityAnnouncement AccessibilityManager.announce()
Progress announcement .accessibilityValue("\(Int(progress * 100)) percent") stateDescription = "$percent percent"
Error announcement Include error message in accessibility label; use .isRejected trait semantics { error(...) }
Remove button Separate accessibility element: .accessibilityLabel("Remove \(fileName)") contentDescription = "Remove $fileName"
Tap target 72px height > 44pt minimum > 48dp minimum
Usage Guidelines

Do

Use the thumbnail slot for image uploads (ID photos, receipts) so users can verify the correct file was picked.

Don't

Show a generic thumbnail placeholder as the final state — either show the real thumbnail or use the plain uploaded state with just the filename.

Do

Always pair the default state with subtext listing accepted formats and size limits so users don't discover constraints only via error state.

Don't

Let users attempt uploads silently only to show an error — preempt format / size violations on the client side.

Do

Use the error state for client-side validation failures (size, format). Show a specific error message indicating what needs to change.

Don't

Use the error state for network failures during upload — those are transient. Show a toast or retry affordance instead.

Criteria Scorecard
ID Criterion Status Notes
C1 Layer Structure & Naming Ready Semantic: input-field, Attach, Trash, Icon Placeholder, upload-file-progress, Subtext Message.
C2 Variant & Property Naming Requires Rework hasLabel yes/no, state has "Upload error" with space, "Uploaded with thumbnail" is orthogonal.
C3 Token Coverage Requires Rework Library-wide boder token typo. Thumbnail bg hardcoded.
C4 Native Mappability Ready Maps to PhotosPicker / DocumentPicker (iOS), GetContent / PickVisualMedia (Android).
C5 Interaction State Coverage Requires Rework No disabled, pressed, or focused states.
C6 Asset & Icon Quality Needs Refinement Thumbnail is a placeholder; Lottie dependency needs documentation.
C7 Code Connect Linkability Needs Refinement Blocked by C2 cleanup.
Variants Inventory (10 total)

5 state × 2 hasLabel = 10 variants. Clean matrix — every combination exists.

StatehasLabelCount
Defaultyes + no2
Uploadingyes + no2
Uploadedyes + no2
Upload erroryes + no2
Uploaded with thumbnailyes + no2
1.0.0 — April 2026Major
Initial Assessment · node 18482:35064
Component assessed — 10 variants (5 state × 2 hasLabel). Lottie progress bar, thumbnail placeholder. Documented
Initial
Property naming issueshasLabel=yes/no, state="Upload error" has a space, "Uploaded with thumbnail" is orthogonal to the state axis. Open
C2 Open
Token typo — All border tokens spelled boder. Library-level rename needed. Open
C3 Open
Thumbnail bg hardcoded#0057E4 @ 5% not tokenized. Open
C3 Open
Missing states — No disabled, pressed, or focused. Open
C5 Open
Thumbnail placeholder + Lottie dependency — Thumbnail is not a slot; Lottie requires asset bundling. Open
C6 Open
Code Connect mappings — Not registered. Open
C7 Open