Skip to content

Drop zone

Pick one photo by dragging it in or tapping to browse. It shows a preview with the file’s name, size and dimensions, and offers Replace and Remove.

CSS
css/components/dropzone.css
JS
js/components/dropzone.js (after form.js)

01 — Example

One photo

Drop an image here or browse. On phones the native picker offers the library and the camera.

02 — Behavior

Script

NameDetail
data-max-sizeThe largest file, in MB. Bigger files show an error.
jewel:filechangeDetail { file, source }, where source is user, api or clear.
el.jewelDropzone.setFile(blob, name), .getFile(), .clear().

03 — Usage

Use it for

Avoid

  • Several files at once. It takes one.
  • Documents. It’s built around image previews.

04 — Accessibility

Notes

  • It’s a real file input with a label, so keyboard and screen reader users browse as normal.
  • The preview’s name, size and dimensions are text, and errors are announced like any field error.

05 — Without Jewel’s JS

What the script does

The script takes a dropped or picked image, checks its type and size, puts it in the file input and shows a preview. The CSS reads only the markup below, so a framework can set it itself and leave out dropzone.js and data-component.

StateSet thisNotes
Emptyhidden on .dropzone__preview and .dropzone__actions.dropzone__empty shows.
Dragging overdata-state="dragover" on .dropzoneAccent border and tint. Remove it on dragleave and drop.
Filledhidden on .dropzone__empty, not on the preview and actions; src and alt on the <img>The script uses an object URL and alt="Preview of photo.jpg", and puts “name · size · width × height” in .dropzone__meta.
Erroraria-invalid="true" on .dropzone__inputTurns the box red. Show the message as a field error (see Text field).
Disableddisabled on .dropzone__inputDashed and dimmed.
SubmittingThe file in .dropzone__inputFor a dropped file, set input.files from a DataTransfer, or send the file yourself.

Events and keyboard

  • Call preventDefault() on dragenter, dragover and drop, or the browser opens the file. The script counts dragenter and dragleave so moving over children doesn’t flicker the state.
  • Replace opens the picker with input.click(). Remove clears the file and moves focus to the input.
  • The script rejects files that don’t match accept or are over data-max-size MB, and keeps only the first of several dropped files.
  • jewel:filechange doesn’t fire without the script.