File input
File selection as a form field: a read-only text field over a hidden file input, which also accepts a drop. The value is always a list of files, whether or not several are allowed.
Usage
Examples
Label and hint
label, hint and placeholder behave as on any other field. iconStart puts an icon at the start of the field, rendered before the chips rather than in their place.
Sizes
size sets the field height to 32, 40 or 48 pixels, and compact takes 4px off it. The chips of a chosen file sit one step below the field.
Multiple files
multiple lets the field take several files. The model is a File array either way.
Clearable
clearable adds a cross that empties the whole selection at once.
Display
display lists the files as names joined by commas, or as one dismissible chip each. The #chip slot replaces a chip and receives its shortened label, remove, and the size and density the field worked out.
Per-file limits
accept takes the browser syntax and filters the system dialog as well as a file dropped on the field. maxSize bounds one file. A refused file never enters the model, and reject fires once per file.
Selection limits
maxFiles and maxTotalSize bound the selection as a whole. Screening runs in a fixed order: type, then size, then count, then total size.
Counter
counter adds a line under the field saying how much has been chosen. The #counter slot replaces it and receives the count, the total in bytes and the sentence already built. Where the counter of VInput and VTextarea counts characters and takes no slot, this one counts files.
Custom icon
pickerIcon is the glyph at the end of the field that opens the system dialog, and it takes any icon value.
States
invalid marks the field as having an error. readonly keeps the selection on show and refuses every way of changing it. disabled greys the field out and takes it out of the tab order. noDrop turns dropping away alone, and loading is purely visual, a spinner replacing the attach icon. pickerIconLabel, clearLabel and loadingText rename what each of them announces.
API
Props
| Prop | Type | Default |
|---|---|---|
multiple | boolean | false |
| Allows several files to be chosen. With one only, every extra file is turned away. | ||
accept | string | none |
| Which kinds of file are accepted, in the browser's own syntax. It is applied twice, and it has to be: as an attribute, which filters the system's file dialog, and again in code, which is the only thing that can filter a dropped file. | ||
display | FileInputDisplay'chip' | 'text' | 'text' |
| How the chosen files are shown: their names joined by commas, or one dismissible chip each. It only means something when several files are allowed; a single name is always text. | ||
maxSize | number | none |
| The largest one file may be, in bytes. | ||
maxTotalSize | number | none |
| The largest the whole selection may be, in bytes. | ||
maxFiles | number | none |
| How many files may be chosen at most. | ||
counter | boolean | false |
| Shows how much has been chosen under the field, "3 files (1.2 MB)". | ||
pickerIcon | IconSource | attach_file |
| The icon at the end of the field, which opens the file dialog. | ||
noDrop | boolean | false |
| Refuses files dropped onto the component: only the dialog then adds any. | ||
size | FileInputSize'sm' | 'md' | 'lg' | 'md' |
| The height of the field: 32, 40 or 48 pixels. | ||
compact | boolean | false |
| Takes 4px off the height, leaving the padding, the text and the icons as they are. | ||
disabled | boolean | false |
| Makes the field unusable, greyed out through the colour tokens. | ||
readonly | boolean | false |
| Shows what was chosen without allowing it to change: no dialog, no drop, no removal. | ||
invalid | boolean | false |
| Marks the field as invalid, for a rule of your own, since nothing here is checked by the browser. | ||
label | string | none |
| The label above the field, tied to it so that clicking it focuses the field. | ||
hint | string | none |
| A line of help under the field, to the left of the counter. It is tied to the field for assistive technology. | ||
placeholder | string | none |
| What the field says while nothing is chosen. It falls back to the design system dictionary. | ||
iconStart | IconSource | none |
An icon inside the field, at the start. It is rendered before the chips rather than in their place. Decorative until a @click:icon-start listener turns it into a button. | ||
iconStartLabel | string | none |
| What the start icon does, in words, once it is clickable. | ||
pickerIconLabel | string | none |
| What the end icon does, in words. It names the button that opens the file dialog, and falls back to the design system dictionary. | ||
loading | boolean | false |
| Shows a spinner in place of the attach icon, while an upload is under way. It changes nothing else: files can still be dropped and the dialog still opens. | ||
loadingText | string | none |
| What screen readers announce while the spinner turns. It falls back to the design system dictionary. | ||
clearable | boolean | false |
| Offers a cross that empties the selection. Worth turning on here more than on an ordinary field: what a picker holds cannot be erased by typing, so the cross is the only way back out of a wrong choice. | ||
clearLabel | string | none |
| What that cross does, in words. It falls back to the design system dictionary. | ||
v-model | File[] | [] |
| Always a list of files, whether or not several are allowed, never a file on its own. The shape does not depend on a prop, so you never have to narrow a union TypeScript cannot discriminate. | ||
Events
| Event | Type |
|---|---|
click:icon-start | [event: MouseEvent] |
The start icon was clicked. Attaching this listener is what turns that icon into a real button, which then needs iconStartLabel. | |
clear | [] |
| The clear cross was pressed. The selection is already empty. | |
change | [files: File[]] |
| The selection changed, with the whole list as it now stands. | |
reject | [rejection: FileRejection] |
| A file was turned away, with which one and why: its kind, its size, or how many there already were. | |
remove | [file: File, index: number] |
One file was taken out through its chip, with the file and the position it held. change follows it with the whole list. | |
Slots
| Slot | Type |
|---|---|
start | {} |
Content at the start of the field, rendered after iconStart rather than in its place. | |
value-end | {} |
Controls of your own inside the field, placed before the ones the field owns: the clear cross and the icon that opens the panel. Those two are the component own affordance, which is why there is no end slot here. | |
chip | FileInputChipSlotProps |
Replaces the chip standing for one file. It receives the name already shortened in the middle so that its extension survives, remove, without which the file could no longer be taken out, and the size and density worked out to sit inside the field. | |
counter | FileInputCounterSlotProps |
Replaces the counter under the field. text is the sentence already built and translated; the count and the total size in bytes are there for a wording of your own. | |
Types
The types the tables above name, written as the library declares them. The ones carrying export can be imported from vectis-ui to type your own code; the others are the shape of what a slot hands out.
export interface BuiltinIcon {
name: string
paths: readonly [string] | readonly [string, string]
}export type ChipSize = 'xs' | 'sm'
export interface FileInputChipSlotProps {
file: File
index: number
label: string
remove: () => void
size: ChipSize
compact: boolean
}export interface FileInputCounterSlotProps {
count: number
bytes: number
text: string
}export type FileRejectReason = 'type' | 'size' | 'count' | 'total-size'
export interface FileRejection {
file: File
reason: FileRejectReason
}export type IconRender =
| { path: string; viewBox?: string }
| { component: Component; props?: Record<string, unknown> }
| { src: string }
| { text: string; class?: string }
| { class: string }export type IconSource = string | BuiltinIcon | IconRender