Formularios

Estado: Beta

Zona para subir archivos

Para las fotos de un producto, la portada de un evento, el slide del inicio o la foto de perfil. La zona reacciona con resorte al arrastrar encima, cada archivo aparece con miniatura, nombre, tamaño y botón para quitarlo, y lo que no cumple (formato, peso, cantidad) se explica donde Field pone sus errores. El input de archivo real se mantiene sincronizado, así que el formulario lo manda como siempre; mientras se envía dice "Subiendo…".

Arrastra tus fotos aquí o elige desde tu equipo PNG, JPG o WEBP · hasta 5 MB · máx. 6
  • tapete-arena-portada.jpg Ya adjunta

La primera es la portada en la tienda.

app/views/… (la demo de arriba)

<%# Fotos de un producto de la tienda y (en el escenario grande) la foto de perfil de una maestra. %>
<div class="@container w-full">
  <div class="mx-auto grid w-full max-w-sm gap-6">
    <%= render Ui::DropzoneComponent.new(label: "Fotos del producto", name: "product[images][]", multiple: true,
          accept: "image/png,image/jpeg,image/webp", max_size: 5.megabytes, max_files: 6,
          attached: [ { url: "/icon.svg", name: "tapete-arena-portada.jpg" } ],
          hint: "La primera es la portada en la tienda.") %>

    <div class="hidden @lg:block">
      <%= render Ui::DropzoneComponent.new(label: "Foto de perfil", name: "user[photo]", mode: :avatar,
            accept: "image/png,image/jpeg,image/webp", max_size: 5.megabytes, placeholder: "AR") %>
    </div>
  </div>
</div>

Qué hace

  • Arrastrar encima: la zona crece apenas y el ícono sube con resorte; soltar agrega.
  • Miniaturas con URL.createObjectURL, liberadas al quitar el archivo o al salir de la página.
  • El input real se sincroniza con DataTransfer; sin direct uploads, se manda con el formulario.
  • Turbo: con turbo:submit-start dice "Subiendo…" y una barra recorre cada archivo.
  • En un solo archivo, lo actual queda atenuado con "Se reemplaza al guardar".

Props

Nombre Tipo Default Descripción
label String — Etiqueta (Ui::FieldComponent), enlazada al input de archivo.
name String nil Nombre del input. Con form + attribute sale del form builder (con [] si es múltiple).
form / attribute FormBuilder / Symbol nil Toma name, id y error del modelo.
multiple Boolean false Varios archivos (has_many_attached).
accept String | Array nil Tipos permitidos ("image/*", "image/png,image/jpeg", ".pdf"); también se validan en el cliente.
max_size Integer (bytes) nil Peso máximo por archivo (5.megabytes).
max_files Integer nil Cuántos archivos nuevos como máximo (solo con multiple).
attached [{ url:, name:, remove_url: }] [] Lo que ya está adjunto (current: es su nombre anterior). Con remove_url aparece un botón de eliminar (turbo_method: :delete).
mode :files | :avatar :files :avatar es compacta y circular, para la foto de perfil (variant: es su nombre anterior).
title / placeholder String según accept Texto de la zona; iniciales del avatar sin foto.
hint / error / required / hide_label — — Los de Ui::FieldComponent.

Accesibilidad