Upload
Drag-and-drop file selection with validation, upload progress, retry, cancellation, and attachment results.
c2-upload owns file selection, drag-and-drop, validation, a multiple-file queue, and the UI around an application-provided upload function. Queue entries are rendered with c2-attachment, so progress, completion, failure, retry, cancellation, metadata, and image previews stay consistent with standalone attachments.
Installation
npm install @c2n/uploadUsage
The examples use a simulated transport so you can select or drop local files and watch their attachment rows progress. In an application, assign your own uploadHandler as a JavaScript property. Resolve with any server result you need later; throw to enter the retry state, and observe signal to cancel active network work when the user removes an attachment.
A single-file uploader hides its picker after accepting a file, leaving the attachment result in its place. Removing that attachment restores the picker. Multiple uploaders stay available until max-files is reached and change their default copy to Upload more, including the remaining capacity. Use variant="compact" for a button-only picker without a drag-and-drop zone; its button uses c2-button and follows the same capacity rules.
const upload = document.querySelector('c2-upload')
upload.uploadHandler = (file, { signal, onProgress }) =>
new Promise((resolve, reject) => {
const request = new XMLHttpRequest()
request.open('POST', '/api/uploads')
request.upload.addEventListener('progress', event => {
if (event.lengthComputable) onProgress((event.loaded / event.total) * 100)
})
request.addEventListener('load', () => resolve(JSON.parse(request.responseText)))
request.addEventListener('error', () => reject(new Error('Upload failed')))
signal.addEventListener('abort', () => request.abort(), { once: true })
request.send(file)
})Use multiple, max-files, max-size, and the native accept syntax to constrain selection. Rejected files remain outside the queue and are reported through file-reject. Set auto-upload="false" to prepare a queue first, then call upload() when the user confirms. The value property returns the selected File[], and a named uploader contributes each file to native FormData. The action and drop-icon slots customize the compact button, while inherited --c2-button__* variables control its appearance. Leave the action slot empty for multiple uploads when you want the built-in remaining-file count.