Monsoon v0.2.0
Made by Alexandre Kohler Star

Media and files

Dropzone

Drag and drop, click to browse or paste files, with type, size and count validation, previews for images, GIFs, video, audio and documents, progress, retry, remove, reorder and a total; the native input stays in sync so a normal form submit sends the files. It needs monsoon.js. Without it the native file input still works.

Media and files18 classesNeeds monsoon.jsLight and dark

Needs monsoon.js. The styles work on their own, and the behavior comes from the optional interactive layer: add <script src="https://cdn.jsdelivr.net/npm/monsooncss/dist/monsoon.js" defer></script> or import 'monsooncss/js'. See the interactive layer.

Example

Full

JavaScript API

Attribute

data-m-dropzone on a .dropzone that wraps a label.dropzone-area with an <input type="file">

Options

OptionDescription
data-m-dropzone-max-sizeLargest file, like 10mb, 500kb or a byte count.
data-m-dropzone-min-sizeSmallest file.
data-m-dropzone-max-filesMost files in the list (1 when the input has no multiple attribute).
data-m-dropzone-acceptAccepted types, defaults to the input accept attribute (image/*, .pdf, application/zip).
data-m-dropzone-simulatefalse turns off the simulated upload progress, files are marked done at once.

Methods

MethodDescription
Monsoon.dropzone(el).filesThe files in list order.
Monsoon.dropzone(el).add(files)Validates and adds files, returns the accepted ones.
Monsoon.dropzone(el).remove(indexOrFile)Removes one file.
Monsoon.dropzone(el).clear()Removes every file.
Monsoon.dropzone(el).retry(index)Uploads one file again.
Monsoon.dropzone(el).validate(files)Returns { accepted, errors } without adding anything.

Events

EventDescription
monsoon:dropzone-changedetail.files after any add, remove or reorder.
monsoon:dropzone-uploadOne per file. Call event.preventDefault() to upload it yourself and report with detail.progress(0 to 1), detail.done(response) and detail.error(message).
monsoon:dropzone-completedetail.file and detail.response when an upload finishes.
monsoon:dropzone-faileddetail.file and detail.error; the row shows a retry button.
monsoon:dropzone-errordetail.errors: [{ file, code, message }] for rejected files (code is type, size, count or duplicate).
monsoon:dropzone-reorderdetail.from, detail.to and detail.files after a drag or Arrow key move on the handle.

Classes

18 classes. Click a name to copy it. Utilities on the same element always win over component defaults, so any of them can be adjusted with plain utility classes.

ClassTypeWhat it does
Base Base class of the dropzone. On a <div> in the example. Sets grid display, gap, width, border, background and shadow, and --tone and --tone-fg.
CSS
.dropzone[data-dragover] .dropzone-glyph {
  translate: 0 -0.25rem;
  scale: 1.08;
}

.dropzone {
  --tone: var(--primary);
  --tone-fg: var(--primary-foreground);
  display: grid;
  gap: 0.75rem;
  min-width: 0;
}
Part Part of the dropzone. On a <label> in the example. Sets flex display, alignment, gap, height, padding and border.
CSS
.dropzone-area:has(> input:focus-visible) {
  outline: var(--m-ring);
  outline-offset: var(--m-ring-offset);
}

.dropzone-area > input {
  order: 1;
  max-width: 100%;
  margin-top: 0.5rem;
  font: inherit;
  color: var(--foreground);
}
Part Part of the dropzone. On a <span> in the example. Sets grid display, alignment, width, height, margin and corner radius.
CSS
.dropzone-glyph > svg {
  width: 1.375rem;
  height: 1.375rem;
}

.dropzone-glyph {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  margin-bottom: 0.375rem;
  border-radius: var(--m-radius-xl);
  background: color-mix(in oklab, var(--tone) 11%, var(--surface));
  box-shadow: inset 0 0 0 var(--m-border-width) color-mix(in oklab, var(--tone) 22%, transparent), var(--m-shadow-xs);
  color: var(--tone);
  transition: translate var(--m-duration) var(--m-ease-spring), scale var(--m-duration) var(--m-ease-spring);
}
Part Part of the dropzone. On a <span> in the example. Sets text color, text size and font weight.
CSS
.dropzone-title {
  color: var(--foreground);
  font-size: 0.9375rem;
  font-weight: 600;
}
Part Part of the dropzone. On a <span> in the example. Sets text color and text style.
CSS
.dropzone-browse {
  color: var(--tone);
  text-decoration: underline;
  text-decoration-thickness: from-font;
  text-underline-offset: 0.2em;
}
Part Part of the dropzone. On a <span> in the example. Sets text color.
CSS
.dropzone-hint {
  color: var(--muted-foreground);
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets grid display, gap, padding, border, corner radius and background.
CSS
.dropzone-errors {
  display: grid;
  gap: 0.25rem;
  padding: 0.625rem 0.875rem;
  border: var(--m-border-width) solid color-mix(in oklab, var(--danger) 28%, transparent);
  border-radius: var(--m-radius-lg);
  background: color-mix(in oklab, var(--danger) 8%, var(--surface));
  color: color-mix(in oklab, var(--danger) 78%, var(--foreground));
  font-size: 0.8125rem;
  animation: m-media-in var(--m-duration) var(--m-ease);
}

@media (prefers-reduced-motion: reduce) {
  .dropzone-area,
  .dropzone-glyph,
  .dropzone-item,
  .dropzone-errors,
  .dropzone-progress,
  .dropzone-progress::before,
  .cropper-grid,
  .cropper-handle::after,
  .avatar-upload-badge,
  .viewer,
  .viewer-image,
  .viewer-thumb,
  .gallery-item,
  .gallery-item img,
  .gallery-check,
  .gallery-check > input,
  .gallery-check > input::before,
  .compare-knob,
  .signature-hint,
  .signature-swatch {
    transition: none;
    animation: none;
  }
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets grid display, gap, margin and padding.
CSS
.dropzone-list {
  display: grid;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets flex display, alignment, gap, width, padding and border, and 5 custom properties.
CSS
.dropzone-item[data-status=done] .dropzone-progress {
  opacity: 0;
}

.dropzone-item[data-kind=pdf] .dropzone-thumb {
  --kind: var(--danger);
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets grid display, alignment, width, height, padding and border.
CSS
.dropzone-handle:hover {
  background: var(--muted);
  color: var(--foreground);
}

.dropzone-handle:focus-visible, .dropzone-play:focus-visible {
  outline: var(--m-ring);
  outline-offset: 0;
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets grid display, alignment, width, height, overflow and corner radius, and --kind.
CSS
.dropzone-thumb > :is(img, video) {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.dropzone-thumb {
  --kind: var(--muted-foreground);
  position: relative;
  display: grid;
  flex: none;
  place-items: center;
  width: 3rem;
  height: 3rem;
  overflow: hidden;
  border-radius: var(--m-radius-md);
  background: color-mix(in oklab, var(--kind) 9%, var(--surface-2));
  box-shadow: inset 0 0 0 var(--m-border-width) color-mix(in oklab, var(--border) 70%, transparent);
  color: var(--kind);
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets grid display, alignment, width, height, absolute position and offsets.
CSS
.dropzone-icon {
  position: relative;
  display: grid;
  place-items: center;
}

.dropzone-icon > svg {
  width: 1.625rem;
  height: 1.625rem;
  stroke-width: 1.5;
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets border, grid display, alignment, width, height and padding.
CSS
.dropzone-handle:focus-visible, .dropzone-play:focus-visible {
  outline: var(--m-ring);
  outline-offset: 0;
}

.dropzone-play {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--kind);
  cursor: pointer;
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets grid display, alignment, gap and width.
CSS
.dropzone-info {
  display: grid;
  flex: 1;
  gap: 0.125rem;
  min-width: 0;
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets overflow, text color, text size, font weight and text style.
CSS
.dropzone-name {
  overflow: hidden;
  color: var(--foreground);
  font-size: 0.875rem;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets text color and text size.
CSS
.dropzone-meta {
  color: var(--muted-foreground);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

.dropzone-item[data-status=error] .dropzone-meta {
  color: color-mix(in oklab, var(--danger) 85%, var(--foreground));
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets height, margin, overflow, corner radius, background and transition.
CSS
.dropzone-progress::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--value, 0%);
  border-radius: inherit;
  background: var(--tone);
  transition: width var(--m-duration) var(--m-ease), background-color var(--m-duration-fast);
}

.dropzone-progress {
  position: relative;
  height: 0.25rem;
  margin-top: 0.25rem;
  overflow: hidden;
  border-radius: var(--m-radius-full);
  background: var(--muted);
  transition: opacity var(--m-duration-slow) var(--m-ease) calc(var(--m-duration-slow) * 2);
}
Modifier Modifier, combined with the dropzone class. Not used in the example above. Sets flex display, alignment, gap, padding, text color and text size.
CSS
.dropzone-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding-inline: 0.25rem;
  color: var(--muted-foreground);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}

Usage

The styles ship inside the same stylesheet as the utilities, and the behavior comes from the optional monsoon.js script, which enhances any element with a matching data-m attribute, including markup added later.

index.html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/monsooncss">
<script src="https://cdn.jsdelivr.net/npm/monsooncss/dist/monsoon.js" defer></script>

<!-- Dropzone: start from the base class, then add modifiers -->
<div class="dropzone max-w-xl" data-m-dropzone data-m-dropzone-max-size="10mb" data-m-dropzone-max-files="8"><label class="dropzone-area"><input type="file" name="attachments" multiple accept="image/*,video/*,audio/*,.pdf,.zip,.csv,.docx,.txt"><span class="dropzone-glyph"><svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 16V4M7 9l5-5 5 5M4 16v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3"/></svg></span><span class="grid gap-1"><span class="dropzone-title">Drop files here or <span class="dropzone-browse">browse</span></span><span class="dropzone-hint">Images, video, audio, PDF and documents up to 10 MB, 8 files at most. You can also paste.</span></span></label></div>

Theme it with --seed on any ancestor, for example style="--seed: #0d9488", and force a scheme with class="dark" or class="light" on a wrapper.

Accessibility

  • Give every control a visible label linked with for, or an aria-label when the purpose is obvious from context. Link help and error text with aria-describedby; invalid styles use :user-invalid, so they appear only after the user interacts.
  • Every interactive part shows a visible focus ring with :focus-visible, and tone colors pair with -foreground tokens that keep text at 4.5:1 or better in light and dark mode.

No recent searches

Try , , or .

Recent

Loading the search index

No results for ""

Check the spelling, or search a class name such as px-4.