v2.1.8
/
  • Get Started
  • Components
  • Composables
  • Typography
  • GitHub
  • Layout
  • App
  • Container
  • Error
  • SidebarLayout
  • Element
  • Advice
  • Alert
  • Avatar
  • AvatarGroup
  • Badge
  • Banner
  • Button
  • Calendar
  • Card
  • Chip
  • Collapsible
  • Countdown
  • FieldGroup
  • Kbd
  • Progress
  • Separator
  • Skeleton
  • Form
  • Checkbox
  • CheckboxGroup
  • ColorPicker
  • FileUpload
  • Form
  • FormField
  • Input
  • InputDate
  • InputMenu
  • InputNumber
  • InputTags
  • InputTime
  • PinInput
  • RadioGroup
  • Range
  • Select
  • SelectMenu
  • Switch
  • Textarea
  • Data
  • Accordion
  • DescriptionList
  • Empty
  • Table
  • TableWrapper
  • Timeline
  • User
  • Navigation
  • Breadcrumb
  • CommandPalette
  • Link
  • NavigationMenu
  • Pagination
  • Stepper
  • Tabs
  • Overlay
  • ContextMenu
  • DropdownMenu
  • Modal
  • Popover
  • Slideover
  • Toast
  • Tooltip
  • Page
  • PageCard
  • PageColumns
  • PageGrid
  • PageLinks
  • PageList
  • Dashboard
  • DashboardGroup
  • DashboardSearch
  • DashboardSearchButton
  • AI Chat
  • soonChatMessage
  • soonChatMessages
  • soonChatPalette
  • soonChatPrompt
  • soonChatPromptSubmit
  • Content
  • ContentSearch
  • ContentSearchButton
  • ContentSurround
  • ContentToc
  • Color Mode
  • ColorModeAvatar
  • ColorModeButton
  • ColorModeImage
  • ColorModeSelect
  • ColorModeSwitch
  • i18n
  • LocaleSelect
  • b24icons
  • b24jssdk
Use our Nuxt starter
v2.1.8
  • Docs
  • Components
  • Composables
  • Typography

FileUpload

A file upload input component.
GitHub
Demo
Nuxt UI

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.

This can be useful when adding a Button component in the #actions slot.
{
  "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.

Drop your image here
{
  "wait": "Loading client-side content..."
}

Description

Use the description prop to set the description of the FileUpload.

Drop your image here
SVG, PNG, JPG or GIF (max. 2MB)
{
  "wait": "Loading client-side content..."
}

Icon

Use the icon prop to set the Icon of the FileUpload.

Drop your image here
SVG, PNG, JPG or GIF (max. 2MB)
{
  "wait": "Loading client-side content..."
}

Color

Use the color prop to change the color of the FileUpload.

Drop your image here
SVG, PNG, JPG or GIF (max. 2MB)
{
  "wait": "Loading client-side content..."
}
The 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.

Drop your image here
SVG, PNG, JPG or GIF (max. 2MB)
{
  "wait": "Loading client-side content..."
}

Layout

Use the layout prop to change how the files are displayed in the FileUpload. Defaults to grid.

This prop only works when variant is area.
Drop your images here
SVG, PNG, JPG or GIF (max. 2MB)
{
  "wait": "Loading client-side content..."
}

Position

Use the position prop to change the position of the files in the FileUpload. Defaults to outside.

This prop only works when variant is area and when layout is list.
Drop your images here
SVG, PNG, JPG or GIF (max. 2MB)
{
  "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.

JPG, GIF or PNG. 2MB Max.

{
  "wait": "Loading client-side content..."
}

With default slot

You can use the default slot to make your own FileUpload component.

JPG, GIF or PNG. 1MB Max.

{
  "wait": "Loading client-side content..."
}

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.

Drop your images here
SVG, PNG, JPG or GIF (max. 2MB)
{
  "wait": "Loading client-side content..."
}
The interactive prop is set to false in this example to prevent the default clickable area.

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.

Drop your images here
SVG, PNG, JPG or GIF (max. 2MB)
{
  "wait": "Loading client-side content..."
}

API

Props

Prop Default Type
as'div'any

The element or component this component should render as.

id string
name string
iconicons.uploadIconComponent

The icon to display.

label string
description string
color'air-tertiary'"air-primary" | "air-primary-success" | "air-primary-alert" | "air-primary-warning" | "air-primary-copilot" | "air-secondary" | "air-secondary-alert" | "air-secondary-accent" | "air-secondary-accent-1" | "air-secondary-accent-2" | "air-tertiary"
variant'area' "button" | "area"

The button variant is only available when multiple is false.

size'md' "xs" | "sm" | "md" | "lg"
layout'grid' "list" | "grid"

The layout of how files are displayed. Only works when variant is area.

position'outside' "inside" | "outside"

The position of the files. Only works when variant is area and when layout is list.

highlightboolean

Highlight the ring color like a focus state.

accept'*' string

Specifies 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").

multiplefalseboolean
resetfalseboolean

Reset the file input when the dialog is opened.

dropzonetrueboolean

Create a zone that allows the user to drop files onto it.

interactivetrueboolean

Make the dropzone interactive when the user is clicking on it.

requiredboolean
disabledboolean
fileIconicons.fileIconComponent

The icon to display for the file.

fileDeletetrueboolean | Partial<ButtonProps>

Configure the delete button for the file. When layout is grid, the default is { color: 'air-secondary-no-accent', size: 'xs' } When layout is list, the default is { color: 'air-tertiary-no-accent' }

fileDeleteIconicons.closeIconComponent

The icon displayed to delete a file.

previewtrueboolean

Show the file preview/list after upload.

modelValue null | File | File[]
b24ui { root?: ClassNameValue; base?: ClassNameValue; wrapper?: ClassNameValue; icon?: ClassNameValue; avatar?: ClassNameValue; label?: ClassNameValue; description?: ClassNameValue; actions?: ClassNameValue; files?: ClassNameValue; file?: ClassNameValue; fileLeadingAvatar?: ClassNameValue; fileWrapper?: ClassNameValue; fileName?: ClassNameValue; fileSize?: ClassNameValue; fileTrailingButton?: ClassNameValue; }
This component also supports all native <input> HTML attributes.

Slots

Slot Type
default{ open: (localOptions?: Partial<UseFileDialogOptions> | undefined) => void; removeFile: (index?: number | undefined) => void; b24ui: object; }
leading{ b24ui: object; }
label{}
description{}
actions{ files?: FileUploadFiles<boolean> | undefined; open: (localOptions?: Partial<UseFileDialogOptions> | undefined) => void; removeFile: (index?: number | undefined) => void; }
files{ files?: FileUploadFiles<boolean> | undefined; }
files-top{ files?: FileUploadFiles<boolean> | undefined; open: (localOptions?: Partial<UseFileDialogOptions> | undefined) => void; removeFile: (index?: number | undefined) => void; }
files-bottom{ files?: FileUploadFiles<boolean> | undefined; open: (localOptions?: Partial<UseFileDialogOptions> | undefined) => void; removeFile: (index?: number | undefined) => void; }
file{ file: File; index: number; }
file-leading{ file: File; index: number; b24ui: object; }
file-name{ file: File; index: number; }
file-size{ file: File; index: number; }
file-trailing{ file: File; index: number; b24ui: object; }

Emits

Event Type
change[event: Event]
update:modelValue[value: File | File[] | null | undefined]

Expose

When accessing the component via a template ref, you can use the following:

NameType
inputRefRef<HTMLInputElement | null>
dropzoneRefRef<HTMLDivElement | null>

Theme

app.config.ts
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'
      }
    }
  }
})
vite.config.ts
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'
          }
        }
      }
    })
  ]
})

ColorPicker

A color picker component.

Form

A form component designed for validation and handling submissions.

On this page

  • Usage
    • Multiple
    • Dropzone
    • Interactive
    • Accept
    • Label
    • Description
    • Icon
    • Color
    • Variant
    • Size
    • Layout
    • Position
  • Examples
    • With Form validation
    • With default slot
    • With files-bottom slot
    • With files-top slot
  • API
    • Props
    • Slots
    • Emits
    • Expose
  • Theme
Releases
Published under MIT License.

Copyright © 2024-present Bitrix24