Usage
Use the v-model directive to control the value of the FileUpload.
{
"wait": "Loading client-side content..."
}Multiple
Use the multiple prop to allow multiple files to be selected.
{
"wait": "Loading client-side content..."
}Dropzone
Use the dropzone prop to enable/disable the droppable area. Defaults to true.
{
"wait": "Loading client-side content..."
}Interactive
Use the interactive prop to enable/disable the clickable area. Defaults to true.
{
"wait": "Loading client-side content..."
}Accept
Use the accept prop to specify the allowed file types for the input. Provide a comma-separated list of MIME types or file extensions (e.g., image/png,application/pdf,.jpg). Defaults to * (all file types).
{
"wait": "Loading client-side content..."
}Label
Use the label prop to set the label of the FileUpload.
{
"wait": "Loading client-side content..."
}Description
Use the description prop to set the description of the FileUpload.
{
"wait": "Loading client-side content..."
}Icon
Use the icon prop to set the Icon of the FileUpload.
{
"wait": "Loading client-side content..."
}Color
Use the color prop to change the color of the FileUpload.
{
"wait": "Loading client-side content..."
}highlight prop is used here to show the focus state. It's used internally when a validation error occurs.Variant
Use the variant prop to change the variant of the FileUpload.
{
"wait": "Loading client-side content..."
}Size
Use the size prop to change the size of the FileUpload.
{
"wait": "Loading client-side content..."
}Layout
Use the layout prop to change how the files are displayed in the FileUpload. Defaults to grid.
variant is area.{
"wait": "Loading client-side content..."
}Position
Use the position prop to change the position of the files in the FileUpload. Defaults to outside.
variant is area and when layout is list.{
"wait": "Loading client-side content..."
}Examples
With Form validation
You can use the FileUpload within a Form and FormField components to handle validation and error handling.
With default slot
You can use the default slot to make your own FileUpload component.
With files-bottom slot
You can use the files-bottom slot to add a Button under the files list to remove all files for example.
With files-top slot
You can use the files-top slot to add a Button above the files list to add new files for example.
API
Props
Slots
Emits
Expose
When accessing the component via a template ref, you can use the following:
Theme
export default defineAppConfig({
b24ui: {
fileUpload: {
slots: {
root: 'relative flex flex-col',
base: 'w-full flex-1 bg-(--b24ui-background)/90 border-(--b24ui-border-color) border-(length:--b24ui-border-width) text-(--b24ui-color) flex flex-col gap-2 items-stretch justify-center rounded-(--ui-border-radius-md) focus-visible:outline-2 transition-[background]',
wrapper: 'flex flex-col items-center justify-center text-center',
icon: 'shrink-0',
avatar: 'shrink-0',
label: 'mt-2 text-(--b24ui-color) font-(--ui-font-weight-medium)',
description: 'mt-1 text-(--b24ui-typography-description-color)',
actions: 'mt-4 flex flex-wrap gap-1.5 shrink-0',
files: '',
file: 'relative',
fileLeadingAvatar: 'shrink-0',
fileWrapper: 'flex flex-col min-w-0',
fileName: 'text-(--b24ui-color) truncate',
fileSize: 'text-(--b24ui-typography-description-color) truncate',
fileTrailingButton: ''
},
variants: {
color: {
'air-primary': {
root: 'light style-filled-inverted'
},
'air-primary-success': {
root: 'light style-filled-success-inverted'
},
'air-primary-alert': {
root: 'light style-filled-alert-inverted'
},
'air-primary-copilot': {
root: 'light style-filled-copilot-inverted'
},
'air-primary-warning': {
root: 'light style-filled-warning-inverted'
},
'air-secondary': {
root: 'style-outline'
},
'air-secondary-alert': {
root: 'light style-tinted-alert'
},
'air-secondary-accent': {
root: 'light style-tinted'
},
'air-secondary-accent-1': {
root: 'style-outline-accent-1'
},
'air-secondary-accent-2': {
root: 'style-outline-accent-2'
},
'air-tertiary': {
root: 'style-outline-no-accent'
}
},
variant: {
area: {
wrapper: 'px-4 py-3',
base: 'p-4'
},
button: {}
},
size: {
xs: {
base: 'text-(length:--ui-font-size-xs)',
icon: 'size-4',
file: 'text-(length:--ui-font-size-xs) px-2 py-1 gap-1',
fileWrapper: 'flex-row gap-1'
},
sm: {
base: 'text-(length:--ui-font-size-xs)',
icon: 'size-4',
file: 'text-(length:--ui-font-size-xs) px-2.5 py-1.5 gap-1.5',
fileWrapper: 'flex-row gap-1'
},
md: {
base: 'text-(length:--ui-font-size-sm)',
icon: 'size-5',
file: 'text-(length:--ui-font-size-xs) px-2.5 py-1.5 gap-1.5'
},
lg: {
base: 'ext-(length:--ui-font-size-sm)',
icon: 'size-5',
file: 'ext-(length:--ui-font-size-sm) px-3 py-2 gap-2',
fileSize: 'ext-(length:--ui-font-size-xs)'
}
},
layout: {
list: {
root: 'gap-2 items-start',
files: 'flex flex-col w-full gap-2',
file: 'min-w-0 w-full rounded-(--ui-border-radius-md) flex items-center border border-(--b24ui-border-color)',
fileTrailingButton: 'ms-auto'
},
grid: {
fileWrapper: 'hidden',
fileLeadingAvatar: 'size-full rounded-lg',
fileTrailingButton: 'absolute -top-1.5 -end-1.5 rounded-(--ui-border-radius-pill) border edge-light:[--ui-btn-background:var(--ui-color-base-white-fixed)] edge-dark:[--ui-btn-background:var(--ui-color-base-white-fixed)] edge-dark:hover:bg-(--ui-color-base-white-fixed)/90 edge-dark:[--ui-btn-color:var(--ui-color-g-content-grey-1)] dark:[--ui-btn-background:var(--ui-color-g-content-grey-1)] dark:hover:bg-(--ui-color-g-content-grey-1)/90 dark:[--ui-btn-color:var(--ui-color-g-content-grey-4)]'
}
},
position: {
inside: '',
outside: ''
},
dropzone: {
true: 'border-dashed data-[dragging=true]:bg-(--ui-color-accent-soft-grey-1)/90'
},
interactive: {
true: ''
},
highlight: {
true: ''
},
multiple: {
true: ''
},
disabled: {
true: 'cursor-not-allowed opacity-75'
}
},
compoundVariants: [
{
class: 'focus-visible:outline-inverted'
},
{
highlight: true,
class: 'border-inverted'
},
{
size: 'xs',
layout: 'list',
class: {
fileTrailingButton: '-me-1'
}
},
{
size: 'sm',
layout: 'list',
class: {
fileTrailingButton: '-me-1.5'
}
},
{
size: 'md',
layout: 'list',
class: {
fileTrailingButton: '-me-1.5'
}
},
{
size: 'lg',
layout: 'list',
class: {
fileTrailingButton: '-me-2'
}
},
{
variant: 'button',
size: 'xs',
class: {
base: 'p-1'
}
},
{
variant: 'button',
size: 'sm',
class: {
base: 'p-1.5'
}
},
{
variant: 'button',
size: 'md',
class: {
base: 'p-1.5'
}
},
{
variant: 'button',
size: 'lg',
class: {
base: 'p-2'
}
},
{
layout: 'grid',
multiple: true,
class: {
files: 'grid grid-cols-2 md:grid-cols-3 gap-4 w-full',
file: 'p-0 aspect-square'
}
},
{
layout: 'grid',
multiple: false,
class: {
file: 'absolute inset-0 p-0'
}
},
{
interactive: true,
disabled: false,
class: 'hover:bg-elevated/25'
}
],
defaultVariants: {
color: 'air-tertiary',
variant: 'area',
size: 'md'
}
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite'
export default defineConfig({
plugins: [
vue(),
bitrix24UIPluginVite({
b24ui: {
fileUpload: {
slots: {
root: 'relative flex flex-col',
base: 'w-full flex-1 bg-(--b24ui-background)/90 border-(--b24ui-border-color) border-(length:--b24ui-border-width) text-(--b24ui-color) flex flex-col gap-2 items-stretch justify-center rounded-(--ui-border-radius-md) focus-visible:outline-2 transition-[background]',
wrapper: 'flex flex-col items-center justify-center text-center',
icon: 'shrink-0',
avatar: 'shrink-0',
label: 'mt-2 text-(--b24ui-color) font-(--ui-font-weight-medium)',
description: 'mt-1 text-(--b24ui-typography-description-color)',
actions: 'mt-4 flex flex-wrap gap-1.5 shrink-0',
files: '',
file: 'relative',
fileLeadingAvatar: 'shrink-0',
fileWrapper: 'flex flex-col min-w-0',
fileName: 'text-(--b24ui-color) truncate',
fileSize: 'text-(--b24ui-typography-description-color) truncate',
fileTrailingButton: ''
},
variants: {
color: {
'air-primary': {
root: 'light style-filled-inverted'
},
'air-primary-success': {
root: 'light style-filled-success-inverted'
},
'air-primary-alert': {
root: 'light style-filled-alert-inverted'
},
'air-primary-copilot': {
root: 'light style-filled-copilot-inverted'
},
'air-primary-warning': {
root: 'light style-filled-warning-inverted'
},
'air-secondary': {
root: 'style-outline'
},
'air-secondary-alert': {
root: 'light style-tinted-alert'
},
'air-secondary-accent': {
root: 'light style-tinted'
},
'air-secondary-accent-1': {
root: 'style-outline-accent-1'
},
'air-secondary-accent-2': {
root: 'style-outline-accent-2'
},
'air-tertiary': {
root: 'style-outline-no-accent'
}
},
variant: {
area: {
wrapper: 'px-4 py-3',
base: 'p-4'
},
button: {}
},
size: {
xs: {
base: 'text-(length:--ui-font-size-xs)',
icon: 'size-4',
file: 'text-(length:--ui-font-size-xs) px-2 py-1 gap-1',
fileWrapper: 'flex-row gap-1'
},
sm: {
base: 'text-(length:--ui-font-size-xs)',
icon: 'size-4',
file: 'text-(length:--ui-font-size-xs) px-2.5 py-1.5 gap-1.5',
fileWrapper: 'flex-row gap-1'
},
md: {
base: 'text-(length:--ui-font-size-sm)',
icon: 'size-5',
file: 'text-(length:--ui-font-size-xs) px-2.5 py-1.5 gap-1.5'
},
lg: {
base: 'ext-(length:--ui-font-size-sm)',
icon: 'size-5',
file: 'ext-(length:--ui-font-size-sm) px-3 py-2 gap-2',
fileSize: 'ext-(length:--ui-font-size-xs)'
}
},
layout: {
list: {
root: 'gap-2 items-start',
files: 'flex flex-col w-full gap-2',
file: 'min-w-0 w-full rounded-(--ui-border-radius-md) flex items-center border border-(--b24ui-border-color)',
fileTrailingButton: 'ms-auto'
},
grid: {
fileWrapper: 'hidden',
fileLeadingAvatar: 'size-full rounded-lg',
fileTrailingButton: 'absolute -top-1.5 -end-1.5 rounded-(--ui-border-radius-pill) border edge-light:[--ui-btn-background:var(--ui-color-base-white-fixed)] edge-dark:[--ui-btn-background:var(--ui-color-base-white-fixed)] edge-dark:hover:bg-(--ui-color-base-white-fixed)/90 edge-dark:[--ui-btn-color:var(--ui-color-g-content-grey-1)] dark:[--ui-btn-background:var(--ui-color-g-content-grey-1)] dark:hover:bg-(--ui-color-g-content-grey-1)/90 dark:[--ui-btn-color:var(--ui-color-g-content-grey-4)]'
}
},
position: {
inside: '',
outside: ''
},
dropzone: {
true: 'border-dashed data-[dragging=true]:bg-(--ui-color-accent-soft-grey-1)/90'
},
interactive: {
true: ''
},
highlight: {
true: ''
},
multiple: {
true: ''
},
disabled: {
true: 'cursor-not-allowed opacity-75'
}
},
compoundVariants: [
{
class: 'focus-visible:outline-inverted'
},
{
highlight: true,
class: 'border-inverted'
},
{
size: 'xs',
layout: 'list',
class: {
fileTrailingButton: '-me-1'
}
},
{
size: 'sm',
layout: 'list',
class: {
fileTrailingButton: '-me-1.5'
}
},
{
size: 'md',
layout: 'list',
class: {
fileTrailingButton: '-me-1.5'
}
},
{
size: 'lg',
layout: 'list',
class: {
fileTrailingButton: '-me-2'
}
},
{
variant: 'button',
size: 'xs',
class: {
base: 'p-1'
}
},
{
variant: 'button',
size: 'sm',
class: {
base: 'p-1.5'
}
},
{
variant: 'button',
size: 'md',
class: {
base: 'p-1.5'
}
},
{
variant: 'button',
size: 'lg',
class: {
base: 'p-2'
}
},
{
layout: 'grid',
multiple: true,
class: {
files: 'grid grid-cols-2 md:grid-cols-3 gap-4 w-full',
file: 'p-0 aspect-square'
}
},
{
layout: 'grid',
multiple: false,
class: {
file: 'absolute inset-0 p-0'
}
},
{
interactive: true,
disabled: false,
class: 'hover:bg-elevated/25'
}
],
defaultVariants: {
color: 'air-tertiary',
variant: 'area',
size: 'md'
}
}
}
})
]
})