378 lines
12 KiB
Markdown
378 lines
12 KiB
Markdown
# File Field
|
|
|
|
A file input to upload multiple files, with ability to drag and drop files.
|
|
|
|
## Import
|
|
|
|
```
|
|
Copyts
|
|
import { FileField } from "@kobalte/core/file-field";
|
|
// or
|
|
import { Root } from "@kobalte/core/file-field";
|
|
```
|
|
|
|
```
|
|
Copyts
|
|
import { FileField } from "@kobalte/core/file-field";
|
|
// or
|
|
import { Root } from "@kobalte/core/file-field";
|
|
```
|
|
|
|
## Features
|
|
|
|
- Supports uploading multiple files at once.
|
|
- Supports drag and drop functionality for uploading files.
|
|
- Supports maximum file limits to restrict the number of files that can be uploaded.
|
|
- Supports file size validation to ensure that files are within the specified size limits.
|
|
- Supports custom validation rules for uploaded files.
|
|
- Supports restricting the types of files that can be uploaded (e.g., images, documents).
|
|
- Displays a list of files that have been selected for upload.
|
|
- Allows users to remove files from the upload list before uploading.
|
|
- Provides a preview of image files before they are uploaded.
|
|
- Displays the size of each file in the upload list.
|
|
- Supports customizing the components with custom styles and classes.
|
|
|
|
## Anatomy
|
|
|
|
The File Field consists of:
|
|
|
|
- **FileField**: The root container for the File Field component.
|
|
- **FileField.Dropzone**: The dropzone area where files can be dragged and dropped.
|
|
- **FileField.Trigger**: The trigger element that opens the file selection dialog.
|
|
- **FileField.Label**: The label for the File Field component to toggle the file selection dialog.
|
|
- **FileField.HiddenInput**: The hidden input element that triggers the file selection dialog.
|
|
- **FileField.ItemList**: The container for the list of files that have been selected for upload.
|
|
- **FileField.Item**: The individual file item in the list of files that have been selected for upload.
|
|
- **FileField.ItemPreview**: The preview for matching file types that have been selected for upload.
|
|
- **FileField.ItemPreviewImage**: The preview image for image files that have been selected for upload.
|
|
- **FileField.ItemName**: The name of the file that has been selected for upload.
|
|
- **FileField.ItemSize**: The size of the file that has been selected for upload.
|
|
- **FileField.ItemDeleteTrigger**: The trigger element to remove a file from the list of files that have been selected for upload.
|
|
- **FileField.Description**: The description that gives the user more information on the file field.
|
|
- **FileField.ErrorMessage**: The error message that gives the user information about how to fix a validation error on the file field.
|
|
|
|
```
|
|
Copytsx
|
|
<FileField>
|
|
<FileField.Label />
|
|
<FileField.Dropzone>
|
|
<FileField.Trigger />
|
|
</FileField.Dropzone>
|
|
<FileField.HiddenInput />
|
|
<FileField.ItemList>
|
|
<FileField.Item>
|
|
<FileField.ItemPreview />
|
|
<FileField.ItemPreviewImage />
|
|
<FileField.ItemSize />
|
|
<FileField.ItemName />
|
|
<FileField.ItemDeleteTrigger />
|
|
</FileField.Item>
|
|
</FileField.ItemList>
|
|
<FileField.Description />
|
|
<FileField.ErrorMessage />
|
|
</FileField>
|
|
```
|
|
|
|
```
|
|
Copytsx
|
|
<FileField>
|
|
<FileField.Label />
|
|
<FileField.Dropzone>
|
|
<FileField.Trigger />
|
|
</FileField.Dropzone>
|
|
<FileField.HiddenInput />
|
|
<FileField.ItemList>
|
|
<FileField.Item>
|
|
<FileField.ItemPreview />
|
|
<FileField.ItemPreviewImage />
|
|
<FileField.ItemSize />
|
|
<FileField.ItemName />
|
|
<FileField.ItemDeleteTrigger />
|
|
</FileField.Item>
|
|
</FileField.ItemList>
|
|
<FileField.Description />
|
|
<FileField.ErrorMessage />
|
|
</FileField>
|
|
```
|
|
|
|
## Example
|
|
|
|
File Upload
|
|
|
|
Drop your files here...Choose files!
|
|
|
|
index.tsxstyle.css
|
|
|
|
```
|
|
Copytsx
|
|
import { FileField } from "@kobalte/core/file-field";
|
|
import "./style.css";
|
|
|
|
function App() {
|
|
return (
|
|
<FileField
|
|
class={style.FileField}
|
|
multiple
|
|
maxFiles={5}
|
|
onFileAccept={(data) => console.log("data", data)}
|
|
onFileReject={(data) => console.log("data", data)}
|
|
onFileChange={(data) => console.log("data", data)}
|
|
>
|
|
<FileField.Label class={style.FileField__label}>
|
|
File Field
|
|
</FileField.Label>
|
|
<FileField.Dropzone class={style.FileField__dropzone}>
|
|
Drop your files here...
|
|
<FileField.Trigger class={style.FileField__trigger}>
|
|
Choose files!
|
|
</FileField.Trigger>
|
|
</FileField.Dropzone>
|
|
<FileField.HiddenInput />
|
|
<FileField.ItemList class={style.FileField__itemList}>
|
|
{(file) => (
|
|
<FileField.Item class={style.FileField__item}>
|
|
<FileField.ItemPreviewImage
|
|
class={style.FileField__itemPreviewImage}
|
|
/>
|
|
<FileField.ItemName class={style.FileField__itemName} />
|
|
<FileField.ItemSize class={style.FileField__itemSize} />
|
|
<FileField.ItemDeleteTrigger
|
|
class={style.FileField__itemDeleteTrigger}
|
|
>
|
|
Delete
|
|
</FileField.ItemDeleteTrigger>
|
|
</FileField.Item>
|
|
)}
|
|
</FileField.ItemList>
|
|
</FileField>
|
|
);
|
|
}
|
|
```
|
|
|
|
```
|
|
Copytsx
|
|
import { FileField } from "@kobalte/core/file-field";
|
|
import "./style.css";
|
|
|
|
function App() {
|
|
return (
|
|
<FileField
|
|
class={style.FileField}
|
|
multiple
|
|
maxFiles={5}
|
|
onFileAccept={(data) => console.log("data", data)}
|
|
onFileReject={(data) => console.log("data", data)}
|
|
onFileChange={(data) => console.log("data", data)}
|
|
>
|
|
<FileField.Label class={style.FileField__label}>
|
|
File Field
|
|
</FileField.Label>
|
|
<FileField.Dropzone class={style.FileField__dropzone}>
|
|
Drop your files here...
|
|
<FileField.Trigger class={style.FileField__trigger}>
|
|
Choose files!
|
|
</FileField.Trigger>
|
|
</FileField.Dropzone>
|
|
<FileField.HiddenInput />
|
|
<FileField.ItemList class={style.FileField__itemList}>
|
|
{(file) => (
|
|
<FileField.Item class={style.FileField__item}>
|
|
<FileField.ItemPreviewImage
|
|
class={style.FileField__itemPreviewImage}
|
|
/>
|
|
<FileField.ItemName class={style.FileField__itemName} />
|
|
<FileField.ItemSize class={style.FileField__itemSize} />
|
|
<FileField.ItemDeleteTrigger
|
|
class={style.FileField__itemDeleteTrigger}
|
|
>
|
|
Delete
|
|
</FileField.ItemDeleteTrigger>
|
|
</FileField.Item>
|
|
)}
|
|
</FileField.ItemList>
|
|
</FileField>
|
|
);
|
|
}
|
|
```
|
|
|
|
## Usage
|
|
|
|
### HTML forms
|
|
|
|
By passing name prop to FileField.HiddenInput, you can use FileField in HTML forms.
|
|
|
|
File Upload
|
|
|
|
Drop your files here...Choose files!
|
|
|
|
Submit Files
|
|
|
|
```
|
|
Copytsx
|
|
function HTMLFormExample() {
|
|
let formRef: HTMLFormElement | undefined;
|
|
|
|
const onSubmit = (e: SubmitEvent) => {
|
|
// handle form submission.
|
|
const formData = new FormData(formRef);
|
|
const uploadedFiles = formData.getAll("uploaded-files");
|
|
};
|
|
|
|
return (
|
|
<form ref={formRef} onSubmit={onSubmit}>
|
|
<FileField
|
|
multiple
|
|
maxFiles={5}
|
|
onFileAccept={data => console.log("data", data)}
|
|
onFileReject={data => console.log("data", data)}
|
|
onFileChange={data => console.log("data", data)}
|
|
>
|
|
<FileField.Label>File Field</FileField.Label>
|
|
<FileField.Dropzone>
|
|
Drop your files here...
|
|
<FileField.Trigger>Choose files!</FileField.Trigger>
|
|
</FileField.Dropzone>
|
|
<FileField.HiddenInput name="uploaded-files" />
|
|
<FileField.ItemList>
|
|
{file => (
|
|
<FileField.Item>
|
|
<FileField.ItemPreviewImage class={"FileField__itemPreviewImage"} />
|
|
<FileField.ItemName />
|
|
<FileField.ItemSize />
|
|
<FileField.ItemDeleteTrigger>Delete</FileField.ItemDeleteTrigger>
|
|
</FileField.Item>
|
|
)}
|
|
</FileField.ItemList>
|
|
</FileField>
|
|
<div>
|
|
<button type="reset">Reset</button>
|
|
<button type="submit">Submit</button>
|
|
</div>
|
|
</form>
|
|
);
|
|
}
|
|
```
|
|
|
|
```
|
|
Copytsx
|
|
function HTMLFormExample() {
|
|
let formRef: HTMLFormElement | undefined;
|
|
|
|
const onSubmit = (e: SubmitEvent) => {
|
|
// handle form submission.
|
|
const formData = new FormData(formRef);
|
|
const uploadedFiles = formData.getAll("uploaded-files");
|
|
};
|
|
|
|
return (
|
|
<form ref={formRef} onSubmit={onSubmit}>
|
|
<FileField
|
|
multiple
|
|
maxFiles={5}
|
|
onFileAccept={data => console.log("data", data)}
|
|
onFileReject={data => console.log("data", data)}
|
|
onFileChange={data => console.log("data", data)}
|
|
>
|
|
<FileField.Label>File Field</FileField.Label>
|
|
<FileField.Dropzone>
|
|
Drop your files here...
|
|
<FileField.Trigger>Choose files!</FileField.Trigger>
|
|
</FileField.Dropzone>
|
|
<FileField.HiddenInput name="uploaded-files" />
|
|
<FileField.ItemList>
|
|
{file => (
|
|
<FileField.Item>
|
|
<FileField.ItemPreviewImage class={"FileField__itemPreviewImage"} />
|
|
<FileField.ItemName />
|
|
<FileField.ItemSize />
|
|
<FileField.ItemDeleteTrigger>Delete</FileField.ItemDeleteTrigger>
|
|
</FileField.Item>
|
|
)}
|
|
</FileField.ItemList>
|
|
</FileField>
|
|
<div>
|
|
<button type="reset">Reset</button>
|
|
<button type="submit">Submit</button>
|
|
</div>
|
|
</form>
|
|
);
|
|
}
|
|
```
|
|
|
|
## API Reference
|
|
|
|
### FileField
|
|
|
|
`FileField` is equivalent to the `Root` import from `@kobalte/core/file-field`.
|
|
|
|
| Prop | Description |
|
|
| --- | --- |
|
|
| `multiple` | `boolean`<br> Allows multiple files to be uploaded |
|
|
| `maxFiles` | `number`<br> The maximum number of files that can be uploaded |
|
|
| `disabled` | `boolean`<br> Disables the file upload component |
|
|
| `accept` | `string | string[] | undefined`<br> The types of files that can be uploaded. |
|
|
| `allowDragAndDrop` | `boolean`<br> Allows files to be dragged and dropped into the component. |
|
|
| `maxFileSize` | `number`<br> The maximum size of the file that can be uploaded in bytes. |
|
|
| `minFileSize` | `number`<br> The minimum size of the file that can be uploaded in bytes. |
|
|
| `onFileAccept` | `(files: File[]) => void`<br> Callback function that is called when file(s) is(are) accepted. |
|
|
| `onFileReject` | `(files: FileRejection[]) => void`<br> Callback function that is called when a file(s) is(are) rejected. |
|
|
| `onFileChange` | `(details: Details) => void`<br> Callback function that is called when the list of files changes. |
|
|
| `validateFile` | `(file: File) => FileError[] | null`<br> Custom validation function for files. |
|
|
|
|
| Data attribute | Description |
|
|
| --- | --- |
|
|
| data-valid | Present when the slider is valid according to the validation rules. |
|
|
| data-invalid | Present when the slider is invalid according to the validation rules. |
|
|
| data-required | Present when the user must slider an item before the owning form can be submitted. |
|
|
| data-disabled | Present when the slider is disabled. |
|
|
| data-readonly | Present when the slider is read only. |
|
|
|
|
`Slider.Trigger` shares the same data-attributes.
|
|
|
|
### FileField.Item
|
|
|
|
| Prop | Description |
|
|
| --- | --- |
|
|
| `file` | `File`<br> Selected file object |
|
|
|
|
### FileField.ItemSize
|
|
|
|
| Prop | Description |
|
|
| --- | --- |
|
|
| `precision` | `number`<br> The number of decimal places to round the file size to. |
|
|
|
|
### FileField.ItemPreview
|
|
|
|
| Prop | Description |
|
|
| --- | --- |
|
|
| `type` | `string`<br> The type of file to preview, only applicable for Images. |
|
|
|
|
## Rendered elements
|
|
|
|
| Component | Default rendered element |
|
|
| --- | --- |
|
|
| `FileField` | `div` |
|
|
| `FileField.Dropzone` | `div` |
|
|
| `FileField.Trigger` | `button` |
|
|
| `FileField.Label` | `label` |
|
|
| `FileField.HiddenInput` | `input` |
|
|
| `FileField.ItemList` | `ul` |
|
|
| `FileField.Item` | `li` |
|
|
| `FileField.ItemPreview` | `div` |
|
|
| `FileField.ItemPreviewImage` | `img` |
|
|
| `FileField.ItemName` | `span` |
|
|
| `FileField.ItemSize` | `span` |
|
|
| `FileField.ItemDeleteTrigger` | `button` |
|
|
| `FileField.Description` | `div` |
|
|
| `FileField.ErrorMessage` | `div` |
|
|
|
|
## Accessibility
|
|
|
|
### Keyboard Interactions
|
|
|
|
| Key | Description |
|
|
| --- | --- |
|
|
| `Space` | When focus is on dropzone, opens the file dialog.<br> When focus is on trigger, opens the file dialog. |
|
|
| `Enter` | When focus is on dropzone, opens the file dialog.<br> When focus is on trigger, opens the file dialog. |
|
|
|
|
Previous[←Dropdown Menu](https://kobalte.dev/docs/core/components/dropdown-menu)Next[Hover Card→](https://kobalte.dev/docs/core/components/hover-card) |