Rapid Rails UI Pro

Upgrade to unlock this component

Get Pro →

Upload

File upload component with optional drag & drop dropzone, preview, and validation.

Key Features

  • Two Modes - Default styled input or drag & drop dropzone
  • File Type Filtering - Accept specific file types with symbols (:image, :pdf, :document)
  • Size Limits - Set max file size per file
  • File Count Limits - Limit number of files for multiple uploads
  • Live Preview - Image thumbnails and file lists with remove buttons
  • Client Validation - Type, size, and count validated before upload
  • Form Builder - Full Rails form integration (f.rui_upload)
  • 5 Sizes - xs, sm, base, lg, xl
  • 3 Variants - Default, filled, outline
  • Full Accessibility - ARIA attributes, keyboard navigation
  • JavaScript API - Programmatic control with data-action attributes

Basic Usage

Simple file upload with label and help text using the styled native file input.

Upload your CV in PDF format

Basic Usage
<%= rui_upload(name: :avatar, label: "Profile Picture") %>

<%= rui_upload(
  name: :resume,
  label: "Resume",
  help_text: "Upload your CV in PDF format"
) %>

Dropzone Mode

Enable drag & drop with the dropzone: true option. Users can drag files onto the area or click to browse.

Drop file here or click to upload

Max size: 10.0 MB

Dropzone Mode
<%= rui_upload(
  name: :document,
  label: "Upload Document",
  dropzone: true
) %>

Tip: The dropzone area highlights when files are dragged over it. The border becomes dashed and the background changes to indicate the active drop state.

Multiple Files

Allow users to select multiple files with the multiple: true option.

Default Mode - Multiple Files

Dropzone Mode - Multiple Files

Drop files here or click to upload

Max size: 10.0 MB • Max files: 10

Drop multiple files here

Multiple Files
<%# Default mode with multiple files %>
<%= rui_upload(
  name: :photos,
  label: "Photo Gallery",
  multiple: true
) %>

<%# Dropzone mode with multiple files %>
<%= rui_upload(
  name: :attachments,
  label: "Attachments",
  dropzone: true,
  multiple: true
) %>

Note: When multiple: true is set, the input name automatically gets [] appended (e.g., photos[]) for proper array handling in Rails.

File Restrictions

Control allowed file types, maximum file size, and maximum number of files.

Accept File Types

Use symbols for common file type presets, or provide a custom MIME type string.

Accepts PNG, JPEG, GIF, WebP, SVG

Accepts PDF, Word documents

Custom MIME type string

Accept File Types
<%# Symbol presets %>
<%= rui_upload(name: :photos, accept: [:image], label: "Images") %>
<%= rui_upload(name: :docs, accept: [:pdf, :document], label: "Documents") %>
<%= rui_upload(name: :data, accept: [:spreadsheet], label: "Spreadsheets") %>
<%= rui_upload(name: :audio, accept: [:audio], label: "Audio Files") %>
<%= rui_upload(name: :video, accept: [:video], label: "Video Files") %>

<%# Custom MIME types %>
<%= rui_upload(name: :file, accept: "image/png,.pdf", label: "Custom") %>

Available Presets

Symbol MIME Types
:image PNG, JPEG, GIF, WebP, SVG
:pdf application/pdf
:document Word (.doc, .docx), OpenDocument
:spreadsheet Excel (.xls, .xlsx), CSV, OpenDocument
:audio MP3, WAV, OGG, AAC, WebM Audio
:video MP4, WebM, OGG Video, MOV
:archive ZIP, RAR, TAR, GZIP, 7Z

Size and Count Limits

Limit file size and number of files. Validation happens client-side before upload.

Files larger than 2MB will be rejected

Drop files here or click to upload

Max size: 10.0 MB • Max files: 3

Upload up to 3 files

Drop files here or click to upload

Accepted: Image • Max size: 5.0 MB • Max files: 5

Size and Count Limits
<%# Max file size %>
<%= rui_upload(
  name: :avatar,
  max_file_size: 2.megabytes,
  label: "Avatar (max 2MB)"
) %>

<%# Max file count %>
<%= rui_upload(
  name: :photos,
  multiple: true,
  max_files: 5,
  label: "Photos (max 5)"
) %>

<%# Combined restrictions %>
<%= rui_upload(
  name: :gallery,
  dropzone: true,
  multiple: true,
  accept: [:image],
  max_file_size: 5.megabytes,
  max_files: 10,
  label: "Gallery"
) %>

Variants

Three visual variants for different design contexts.

Default

Filled

Outline

Variants
<%= rui_upload(name: :file, variant: :default, label: "Default") %>
<%= rui_upload(name: :file, variant: :filled, label: "Filled") %>
<%= rui_upload(name: :file, variant: :outline, label: "Outline") %>

Sizes

Five size options from extra small to extra large.

Sizes
<%= rui_upload(name: :file, size: :xs, label: "Extra Small") %>
<%= rui_upload(name: :file, size: :sm, label: "Small") %>
<%= rui_upload(name: :file, size: :base, label: "Base (default)") %>
<%= rui_upload(name: :file, size: :lg, label: "Large") %>
<%= rui_upload(name: :file, size: :xl, label: "Extra Large") %>

States

Required, disabled, and error states.

States
<%= rui_upload(name: :file, required: true, label: "Required") %>
<%= rui_upload(name: :file, disabled: true, label: "Disabled") %>
<%= rui_upload(name: :file, error: "File type not accepted", label: "With Error") %>

Form Builder Integration

Use with Rails form builder for automatic object binding.

Form Builder Usage
<%= form_with model: @user do |f| %>
  <%# Single file upload %>
  <%= f.rui_upload(:avatar,
    label: "Profile Picture",
    accept: [:image],
    max_file_size: 2.megabytes
  ) %>

  <%# Multiple files with dropzone %>
  <%= f.rui_upload(:documents,
    label: "Documents",
    dropzone: true,
    multiple: true,
    accept: [:pdf, :document],
    max_files: 10
  ) %>

  <%= f.rui_button("Upload") %>
<% end %>

Note: When using f.rui_upload, the component automatically generates the correct name (e.g., user[avatar]) and handles multiple file arrays.

ActiveStorage Integration

The upload component is storage-agnostic - it renders a standard file input that works with ActiveStorage, Shrine, CarrierWave, or any file handling approach.

ActiveStorage Example
<%# Model with has_one_attached %>
class User < ApplicationRecord
  has_one_attached :avatar
  has_many_attached :documents
end

<%# Form %>
<%= form_with model: @user do |f| %>
  <%= f.rui_upload(:avatar,
    label: "Avatar",
    accept: [:image]
  ) %>

  <%= f.rui_upload(:documents,
    label: "Documents",
    multiple: true
  ) %>
<% end %>

Real-World Example: Post Form

See the upload component in action on the New Post and Posts pages.

Accessibility

The Upload component follows WAI-ARIA best practices for file upload controls.

ARIA Attributes

  • Help text and errors linked via aria-describedby
  • Required fields include aria-required="true"
  • Error messages displayed with role="alert"

Keyboard Navigation

  • Tab focuses the upload area
  • Enter or Space opens the file picker
  • Focus states are clearly visible with ring styles
  • Remove buttons on file items are keyboard accessible

Semantic HTML

  • Uses native <input type="file"> element
  • Labels use for attribute linked to input id
  • Dropzone uses proper ARIA roles for drag-and-drop

Screen Reader Support

  • File selection status is announced
  • Validation errors are announced for file type/size issues
  • File list is announced with count and names

JavaScript API

The upload uses the upload Stimulus controller for file handling, drag & drop, preview, and validation.

Stimulus Actions

Trigger upload behavior from any element:

Action Description
upload#triggerFileInput Open the native file picker dialog
upload#selectFiles Handle files selected via input (called on change event)
upload#handleDragOver Show visual feedback when dragging files over dropzone
upload#handleDragLeave Remove visual feedback when dragging leaves dropzone
upload#handleDrop Process files dropped onto the dropzone
upload#removeFile Remove a file from the preview list
Using Stimulus Actions

Drop files here or click to browse

Controller Values

Configure the upload behavior:

Value Type Default Description
multiple Boolean false Allow selecting multiple files
maxFiles Number 10 Maximum number of files allowed
maxFileSize Number 10485760 Maximum file size in bytes (10 MB default)
accept String "" Accepted MIME types (comma-separated)

Programmatic Control

Control the upload directly via Stimulus controller:

// Get the controller instance
const element = document.querySelector('[data-controller="upload"]')
const controller = this.application.getControllerForElementAndIdentifier(element, 'upload')

// Open file picker programmatically
controller.triggerFileInput({ preventDefault: () => {} })

// Access current files
console.log('Selected files:', controller.files)

// Clear all files by resetting
controller.files = []
// Clear preview using DOM methods
while (controller.previewTarget.firstChild) {
  controller.previewTarget.removeChild(controller.previewTarget.firstChild)
}

// Check validation settings
console.log('Max file size:', controller.maxFileSizeValue)
console.log('Accepted types:', controller.acceptValue)

Note: The upload controller validates files client-side before adding them to the preview. Files that exceed size limits or don't match accepted types are rejected with an error message displayed in the error target.

API Reference

rui_upload

File upload component with drag-and-drop, preview, and validation

Parameter Type Default Description
name_or_method* Symbol/String Positional first arg - name for standalone, method for form builder

Appearance

Visual styling options

Parameter Type Default Description
variant Symbol :dropzone Visual style
:dropzone :button :minimal
color Symbol :primary Accent color - semantic or any Tailwind color
size Symbol :base Component size
:xs :sm :base :lg :xl
shape Symbol :rounded Border radius
:square :rounded :pill

File Validation

File type and size validation options

Parameter Type Default Description
accept String/Array Accepted file types (e.g., 'image/*', '.pdf', ['image/png', 'image/jpeg'])
max_size Integer/String Maximum file size in bytes or human format ('5MB')
min_size Integer/String Minimum file size

Preview Options

File preview configuration

Parameter Type Default Description
preview Boolean true Show file preview after selection
preview_size Symbol :base Preview thumbnail size
:xs :sm :base :lg :xl
remove_button Boolean true Show remove button on preview

Multiple Files

Multiple file upload options

Parameter Type Default Description
multiple Boolean false Allow multiple file selection
max_files Integer Maximum number of files (when multiple)

Labels & Text

Text options

Parameter Type Default Description
label String Label text displayed above upload
help_text String Help text displayed below upload
dropzone_text String Custom text inside dropzone
button_text String Custom button text

States

State options

Parameter Type Default Description
required Boolean false Show required indicator (*)
disabled Boolean false Disable the upload

Form Builder

Options when used with Rails form builder (f.rui_upload)

Parameter Type Default Description
form FormBuilder Rails form builder instance
object Object/Symbol Object to bind upload to
direct_upload Boolean false Enable Active Storage direct upload

Related Components