components / fileupload

FileUpload

Styled upload field shell with file-list feedback and proof-backed trigger sizing.

Overview

What it is

This section explains the intent of the component before the implementation details.

  • FileUpload gives DK a durable upload shell so teams do not reinvent choose-file affordances, helper text, and selected file feedback.
  • It keeps the contract intentionally simple while still fitting the system field family.

Aliases

upload field

Decision guide

How to choose it

Use these notes to decide quickly whether this is the right DK component for the job.

Decision guide

  • Choose FileUpload when the interaction should feel deliberate, documented, and reusable across product surfaces.
  • If the scenario is more specialized than the current FileUpload contract, prefer a simpler component or build a dedicated workflow on top of the lower-level DK primitives.

Do

  • Keep the FileUpload label, value, or status language direct enough to scan quickly.
  • Use the documented size and state recipes instead of inventing one-off variants in product code.

Do not

  • Do not hide the main purpose of FileUpload behind decorative copy or overloaded surface treatments.
  • Do not stretch FileUpload into a workflow it was not designed to handle just because the visuals are close.

Usage

When to use

Prefer these situations when choosing this component.

  • Use FileUpload when the user needs to choose one or more local files through a standard file picker.
  • Use helper text to clarify accepted formats or expectations.

Usage

When not to use

These patterns are better served by a different component or a simpler surface.

  • Do not use FileUpload for drag-and-drop media workspaces or complex upload dashboards in this v1 contract.
  • Do not hide file constraints; place them in the description or nearby supporting copy.

Anti-patterns

  • Using FileUpload as a generic layout container instead of a purpose-built interaction or content surface.
  • Forking the documented recipe in product code instead of extending the shared DK contract.

Migration notes

  • Migrate legacy fileupload usage by mapping existing variants and states onto the documented DK props before porting any custom styling.
  • Treat the docs examples as the reference contract for accessibility and event behavior during adoption.

Anatomy

Structural parts

The anatomy explains which pieces matter to the recipe and accessibility model.

field wrapper

root

Carries the label, helper text, and chosen-file feedback.

file picker button

trigger

Opens the native file chooser.

selected file summary

file-list

Shows the chosen file names after selection.

API

Public interface

The docs contract distinguishes props, DOM events, and slots so integration behavior is explicit.

Props

NameTypeDefaultDescription
labelstringVisible label used for the field or control.
descriptionstringSupporting helper copy rendered below or beside the main label.
errorstringValidation or problem copy rendered in the error slot when present.
placeholderstringPlaceholder text shown before a user makes a selection or enters text.
requiredbooleanfalseMarks the field or control as required for form semantics and docs examples.
disabledbooleanfalseDisables interaction and exposes the correct non-interactive semantics for the control.
namestringForm field name used for native form submission.
idstringOptional id used to bind external labels or descriptions to the component.
size'sm' | 'md' | 'lg''md'Chooses the compiled size recipe for the component.
multiplebooleanfalseAllows selecting more than one file.
acceptstringNative file accept filter.
buttonLabelstring'Choose files'Visible trigger label.
onChange(detail: { value: string | undefined }) => voidCallback fired after the file selection changes.
themeThemeContractOverrides the compiled DK theme used to resolve tokens and recipes for this component.

Events

NamePayloadDescription
change{ value: string | undefined }Fires when the component commits a new value.

Slots

NameDescription
defaultFileUpload is prop-driven in v1 and does not expose content slots.

Recipes

Variants, sizes, and states

These notes summarize the intended recipe surface rather than exposing raw implementation detail first.

Variants

  • default: FileUpload uses one shell and varies mainly by size.

Sizes

  • sm: Compact upload affordance.
  • md: Default upload affordance.
  • lg: Larger upload affordance for touch-heavy surfaces.

States

  • rest: No file has been selected.
  • selected: One or more files have been selected.
  • disabled: The upload control cannot be activated.

Accessibility

Accessibility contract

This is the behavior the component promises to assistive tech and keyboard users today.

Semantics

  • Uses standard field labeling through visible labels, descriptions, and error text.
  • Exposes disabled and required semantics through the underlying form control.
  • Uses the native file input under a styled DK field shell.

Keyboard

  • Supports native focus and text entry behavior.
  • Supports standard focus and activation behavior through the trigger.

Screen readers

  • Connects visible label, helper text, and error text to the native control.
  • Label and helper text remain associated with the underlying file input.

Checklist

  • Verify the visible label or title still produces a clear accessible name.
  • Verify focus remains obvious in every supported state and size.
  • Verify disabled, selected, and error states do not rely on color alone.

Implementation

Tokens and slot vars

This section shows the representative compiled slot variables that the runtime consumes for the selected design system.

root

--dk-field-stack-gap
0.45rem

label

--dk-field-label-color
#16181c
--dk-field-label-size
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
--dk-field-label-weight
600

field

--dk-file-upload-bg
#f2f5fb
--dk-file-upload-fg
#16181c
--dk-file-upload-border
#95989d
--dk-file-upload-radius
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
--dk-file-upload-padding
clamp(1.778rem, 1.6296rem + 0.658vw, 2.222rem)
--dk-file-upload-gap
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
--dk-file-upload-button-bg
#d7e9ff
--dk-file-upload-button-fg
#000f4d
--dk-file-upload-button-radius
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
--dk-file-upload-button-block-size
44px
--dk-file-upload-button-inline-padding
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
--dk-file-upload-button-font-size
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
--dk-file-upload-copy-size
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)

button

--dk-file-upload-button-weight
650

copy

--dk-file-upload-copy-color
#16181c

list

--dk-file-upload-list-gap
clamp(0.563rem, 0.5156rem + 0.208vw, 0.703rem)

item

--dk-file-upload-item-size
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)

description

--dk-field-description-color
#16181c
--dk-field-description-size
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)

error

--dk-field-error-color
#cc272e
--dk-field-error-size
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)

Implementation notes

  • FileUpload stays close to the native file input contract so browsers and assistive technology can do their job.

Implementation checklist

  • Use the public component API first and only drop to lower-level primitives when the component contract genuinely does not fit.
  • Keep theme overrides token-driven so proofs and recipes stay meaningful.
  • Verify the shipped examples and proof fixtures still represent the real product scenario you are implementing.

Examples

Copy-paste examples

Each example is intentionally practical, grouped by starter, common pattern, and edge-case coverage.

Examples
3
Depth
baseline

Starter

1 example

starter

Starter: one asset picker

A basic upload affordance with helper text.

Copy snippet

<FileUpload label="Assets" description="Upload supporting files." />

Common patterns

1 example

common

Common: multi-file upload

Allow multiple files when the workflow expects a batch.

Copy snippet

<FileUpload label="Attachments" multiple={true} />

Edge cases

1 example

edge

Edge: filtered file types

Use `accept` when the workflow only supports known formats.

Copy snippet

<FileUpload label="Brand assets" accept=".png,.svg,.pdf" buttonLabel="Choose assets" />

Verification

Curated proof fixtures

Proofs stay visible in the docs so the system shows what it can guarantee, not just what it can render.

default (size=sm)

pass

size=sm

  • Contrast: 98.5 Lc
  • Target: 44px
  • Layout: 0 / 280, 360, 460

default (size=md)

pass

size=md

  • Contrast: 98.5 Lc
  • Target: 44px
  • Layout: 0 / 280, 360, 460

large

pass

size=lg

  • Contrast: 98.5 Lc
  • Target: 48px
  • Layout: 0 / 280, 360, 460

invalid (size=sm)

pass

size=sm

  • Contrast: 98.5 Lc
  • Target: 44px
  • Layout: 0 / 280, 360, 460

invalid (size=md)

pass

size=md

  • Contrast: 98.5 Lc
  • Target: 44px
  • Layout: 0 / 280, 360, 460

invalid (size=lg)

pass

size=lg

  • Contrast: 98.5 Lc
  • Target: 48px
  • Layout: 0 / 280, 360, 460