ngx-accessible-dropzone
v1.0.0
Published
A tiny, zero-dependency, fully accessible drag-and-drop file upload component for Angular (standalone). Keyboard-operable, screen-reader friendly, themeable, with optional size validation.
Maintainers
Readme
ngx-accessible-dropzone
A tiny, zero-dependency, fully accessible drag-and-drop file upload component for Angular (standalone).
Most "drag & drop" upload snippets only handle the mouse. This one is keyboard-operable (Enter / Space), screen-reader labelled (role="button" + aria-label), shows a clear focus ring, and adds an optional client-side size guard — in a single standalone component with no third-party dependencies.
It was originally built for and battle-tested across 30+ tools on Confileo — a free online PDF & file toolkit — then extracted and cleaned up as a reusable, framework-agnostic-styled component.
✨ Features
- ♿ Accessible by default — keyboard support, focus ring, ARIA labelling.
- 🪶 Zero dependencies — only
@angular/core+@angular/common. - 🧩 Standalone component — no NgModule needed.
- 🎨 Themeable via CSS custom properties (no CSS framework required).
- 📦 Optional size guard with a customizable rejection message.
- 🖼️ Custom icon via content projection.
- ⚡ OnPush change detection.
📦 Installation
npm install ngx-accessible-dropzonePrefer not to add a dependency? You can also just copy
src/lib/accessible-dropzone.component.tsstraight into your project — it's a single self-contained file.
🚀 Usage
import { Component } from '@angular/core';
import { AccessibleDropzoneComponent } from 'ngx-accessible-dropzone';
@Component({
selector: 'app-demo',
standalone: true,
imports: [AccessibleDropzoneComponent],
template: `
<adz-dropzone
accept=".pdf"
[maxSizeMB]="100"
label="Drop your PDF here or click to browse"
hint="Up to 100 MB"
(filesSelected)="onFiles($event)"
(rejected)="onError($event)"
></adz-dropzone>
`,
})
export class DemoComponent {
onFiles(files: File[]) { console.log('Accepted:', files); }
onError(message: string) { console.warn(message); }
}Custom icon
<adz-dropzone label="Upload an image" (filesSelected)="onFiles($event)">
<span adzIcon>
<!-- any SVG / element -->
<svg width="48" height="48" viewBox="0 0 24 24" ...></svg>
</span>
</adz-dropzone>⚙️ API
Inputs
| Input | Type | Default | Description |
|-------|------|---------|-------------|
| accept | string | '' | Native picker filter, e.g. ".pdf" or "image/*". |
| multiple | boolean | false | Allow selecting several files. |
| maxSizeMB | number | 0 | Client-side size limit in MB (0 disables the check). |
| label | string | 'Drop your file here or click to browse' | Headline text. |
| hint | string | '' | Sub-text under the label. |
| disabled | boolean | false | Disables interaction. |
| tooLargeMessage | string | 'File exceeds the maximum size of {max} MB.' | Message emitted on (rejected); {max} is replaced with maxSizeMB. |
Outputs
| Output | Payload | Description |
|--------|---------|-------------|
| filesSelected | File[] | The accepted files. |
| rejected | string | Error message (e.g. file too large). |
🎨 Theming
Override any of these CSS custom properties on the host or an ancestor:
adz-dropzone {
--adz-accent: #ff6b35; /* hover / focus / icon color */
--adz-border: #e5e7eb; /* idle border */
--adz-bg: #f9fafb; /* idle background */
--adz-bg-hover: rgba(255,107,53,.03);
--adz-focus-ring: rgba(255,107,53,.25);
--adz-text: #1a1a2e; /* label color */
--adz-hint: #9ca3af; /* hint color */
--adz-radius: 0; /* border radius */
--adz-padding: 60px 24px; /* inner padding */
}♿ Accessibility
- The zone is a real
role="button"withtabindex="0"and anaria-label. EnterandSpaceopen the file picker, just like a click.- A visible
:focus-visiblering is provided for keyboard users. aria-disabledand a-1tabindex are set whendisabled.
📄 License
Built and maintained by the team behind Confileo — free online tools to compress, convert, merge, split, edit and protect PDFs and files, in English and Arabic. If this component saved you time, a ⭐ on the repo is appreciated!
