GUILD OF GLEKS UIv21.19.0

gog-file-upload

File Upload 21.18.0

Choosing files, by the system picker or by a drop. The native accept only filters what the picker offers — a reader can switch it to "All files", and a file dropped on the page is never checked against it at all. This component checks every file, however it arrived, against accept, maxSize and maxFiles, and says what it refused and why. It does not upload: it holds File objects, and sending them is your app's.

Overview

typescript
import { FileUploadComponent } from '@guildofgleks/ui';

@Component({
  // ...
  imports: [FileUploadComponent],
})

A label, a hint, and the rules. A click anywhere on the zone opens the picker:

Drop files here or browsePDF, up to 5 MB
<gog-file-upload
  label="Contract"
  hint="PDF, up to 5 MB"
  accept=".pdf"
  [maxSize]="5 * 1024 * 1024"
/>

Examples

Sizes

Five text steps; the zone's padding grows with them.

Drop files here or browsexsm
Drop files here or browsesm
Drop files here or browsemd
Drop files here or browselg
Drop files here or browseslg
@for (size of sizes; track size) {
  <gog-file-upload label="Attachment" [hint]="size" [size]="size" />
}

States

Default, with an error (the border and the message take the danger colour), and disabled. A drop on a disabled zone is still caught, so the browser does not navigate to the file.

Drop files here or browsePDF
Drop files here or browsePDF
Attach the signed contract
Drop files here or browsePDF
<gog-file-upload label="Contract" hint="PDF" accept=".pdf" />
<gog-file-upload
  label="Contract"
  hint="PDF"
  accept=".pdf"
  errorMessage="Attach the signed contract"
/>
<gog-file-upload label="Contract" hint="PDF" accept=".pdf" disabled />

Forms

A ControlValueAccessor holding a File[]. errorDisplay="auto" shows the message once the control is touched and invalid; the GOG_CONFIG.control.errorDisplay key sets it app-wide.

Drop files here or browse

0 file(s) · touched false · valid false

<div>
  <gog-file-upload
    label="Signed contract"
    accept=".pdf"
    errorMessage="Attach the signed contract"
    errorDisplay="auto"
    [formControl]="contract"
  />
  <p>
    {{ contract.value.length }} file(s) · touched {{ contract.touched }} · valid
    {{ contract.valid }}
  </p>
</div>
<div>
  <gog-button variant="secondary" size="sm" (gogClick)="contract.markAsTouched()">
    markAsTouched()
  </gog-button>
  <gog-button variant="ghost" size="sm" (gogClick)="contract.reset()">reset()</gog-button>
</div>

Validation

The check is the component’s, not the picker’s.

accept, maxSize, maxFiles and gogReject

Drop an executable, a file over 1 MB, or a fourth file. Each refusal comes back from gogReject with its reason — 'type', 'size' or 'count' — and a polite live region says it. maxFiles counts the files already chosen. gogFileMatchesAccept(file, accept) is exported for the same check elsewhere.

Drop files here or browsePDF or images, up to 1 MB each, at most three

0 file(s) chosen

<gog-file-upload
  label="Documents"
  hint="PDF or images, up to 1 MB each, at most three"
  accept=".pdf,image/*"
  multiple
  [maxSize]="1024 * 1024"
  [maxFiles]="3"
  [(value)]="files"
  (gogReject)="rejected.set($event)"
/>
<p>{{ files().length }} file(s) chosen</p>
@for (refusal of rejected(); track refusal.file) {
  <p>{{ refusal.file.name }} — refused: {{ refusal.reason }}</p>
}

Without multiple

The field holds one file, and a new one replaces it.

Drop files here or browseOne image; a new one replaces it
<gog-file-upload label="Avatar" hint="One image; a new one replaces it" accept="image/*" />

Accessibility

The drop zone is a mouse affordance; the control is a real file input.

  • The input is the control — the real <input type="file"> lies over the whole zone, so it is what takes focus, is named by label (or ariaLabel), is described by the hint and the error, and opens with Enter or Space. The zone shows the input's focus ring.
  • What happened, said — a permanently mounted polite region announces "2 files added" and "setup.exe was not added: its type is not accepted" (filesAdded, fileRejected).
  • Removing — each file's remove button is named "Remove report.pdf" (fileRemove), and after a press focus moves to the next remove button, or back to the input, never to <body>. The button paints 16px and takes the pointer across 24.

API Reference

gog-file-upload inputs

NameTypeDefaultDescription
valueFile[] (model)[]The chosen files, two-way. Also what an attached form control holds.
multiplebooleanfalseOff: a new file replaces the one there.
acceptstring''The native syntax (.pdf, image/*, application/json), enforced on every file, picked or dropped.
maxSizenumber | nullnullBytes, per file. Unset, any size.
maxFilesnumber | nullnullThe most files held at once, counting those already chosen.
labelstring''The input’s name.
hintstring''A line in the zone describing what is accepted; also the input’s description.
ariaLabelstring''Names the input when there is no label.
errorMessagestring''The error line, and the zone’s danger border.
errorDisplayGogErrorDisplay | undefined'manual'When the error shows. Unset, GOG_CONFIG.control.errorDisplay.
disabledbooleanfalse
sizeGogSize'md''xsm' | 'sm' | 'md' | 'lg' | 'slg'.

gog-file-upload outputs

NamePayloadDescription
valueChangeFile[]The value, after a pick, a drop or a removal.
gogRejectGogFileRejection[]Every file one pick or drop refused, as { file, reason: 'type' | 'size' | 'count' }.

Global Configuration

Set any of these once with provideGogConfig() instead of repeating them on every instance — an instance's own input still wins when it sets one itself. See Global Configuration for the full reference.

  • GOG_CONFIG.control.errorDisplay
  • GOG_CONFIG.labels.fileDrop — the prompt before "browse"
  • GOG_CONFIG.labels.fileBrowse
  • GOG_CONFIG.labels.fileRemove — a formatter: (name) => string
  • GOG_CONFIG.labels.filesAdded — a formatter: (count) => string, announced
  • GOG_CONFIG.labels.fileRejected — a formatter: (name, reason) => string, announced

Styling Tokens

Every CSS custom property the file upload paints with. Override any of them — on a single instance, a subtree, or a theme — to restyle it. See the Theming guide for the full token-layering model, or the Theme Generator to tweak these live.

TokenDescription
--gog-file-upload-font-family / -line-height / -gapThe component’s typeface, leading, and the space between label, zone, list and error.
--gog-file-upload-label-font-family / -label-font-size / -label-line-height / -label-font-weight / -label-color / -label-text-transform / -label-letter-spacingThe label above the zone — the field label’s tokens by reference, so it matches every other field.
--gog-file-upload-xsm-font-size / -sm-font-size / -md-font-size / -lg-font-size / -slg-font-sizeThe prompt at each size.
--gog-file-upload-xsm-zone-padding / -sm-zone-padding / -md-zone-padding / -lg-zone-padding / -slg-zone-paddingThe drop zone’s padding at each size. A surface, so one value on every side.
--gog-file-upload-zone-gap / -zone-border-width / -zone-border-color / -zone-radius / -zone-bgThe dashed zone at rest. The dash is the control boundary colour, so the zone stays visible at 3:1.
--gog-file-upload-zone-active-border-color / -zone-active-bg / -transition-durationThe zone under the pointer and while a file is dragged over it.
--gog-file-upload-prompt-color / -browse-color / -browse-font-weight"Drop files here or browse". "browse" is marked by its underline and weight, not a colour.
--gog-file-upload-icon-color / -icon-font-size / -icon-line-heightThe upload glyph above the prompt.
--gog-file-upload-hint-color / -hint-font-size / -hint-line-heightThe hint line in the zone; the error line uses the same size.
--gog-file-upload-list-gap / -file-gap / -name-color / -remove-radiusThe list of chosen files: rows, the space within a row, the file name, and the remove button’s corner.
--gog-file-upload-error-colorThe error line, and the zone’s border while there is one.
--gog-file-upload-focus-ring-width / -focus-ring-offset / -focus-ring-colorThe ring the zone draws while the input inside it has keyboard focus, and the remove button’s.
--gog-file-upload-disabled-opacityThe whole component, disabled.