SimpleDropzone
Choose one file with the file picker or by dropping it on a box, with the file name and a button to remove it.
Simple picks one file. The reader opens the file picker from the box, or drops a file on
it; the chosen file's name appears with a button to remove it. Your application receives the
File and does the rest: checking, reading, uploading. To show files that are uploading, use
Attachment.
A CSV file with one participant per row.
// apps/docs/examples/ui/simple-dropzone.tsx'use client';
import {useState} from 'react';
import {formatByteSize} from '@workspace/active-format';import {SimpleDropzone} from '@workspace/active-ui/components/composed/simple-dropzone';import { Field, FieldDescription, FieldError,} from '@workspace/active-ui/components/primitives/field';
/** * One file, chosen with the file picker or dropped on the box. The * instruction is the field's label. The check on the type is the * application's: `accept` only filters the picker, so a dropped file of * another type gets an error here. Nothing is uploaded. */export default function SimpleDropzoneExample() { const [file, setFile] = useState<File | null>(null); const wrongType = file !== null && !file.name.toLowerCase().endsWith('.csv'); return ( <Field className="w-full max-w-md" data-invalid={wrongType || undefined}> <SimpleDropzone accept=".csv,text/csv" onFileChange={setFile} instruction="Choose a CSV file, or drop it here" clearFileLabel="Remove the file" aria-invalid={wrongType || undefined} aria-describedby="participants-file-state" /> {wrongType ? ( <FieldError id="participants-file-state"> Choose a CSV file. {file.name} is not one. </FieldError> ) : ( <FieldDescription id="participants-file-state"> {file ? `${file.name}, ${formatByteSize(file.size, 'en', {system: 'decimal'})}` : 'A CSV file with one participant per row.'} </FieldDescription> )} </Field> );}What the composition adds#
The file input itself is the control. It is visually hidden but focusable, and the instruction is its
<label>: clicking the box or pressingEnterorSpaceon the focused field opens the picker. The box shows the focus ring.Dropping is an addition, never the only way in.
disabledcloses every way in: the field, the label, the remove button and dropping.aria-andinvalid aria-land on the file input, so an error is read with the field.describedby
One file only, with no maximum size, no progress and no error message of its own.
Usage#
import {SimpleDropzone} from '@workspace/active-ui/components/composed/simple-dropzone';
<SimpleDropzone accept=".csv,text/csv" onFileChange={setFile} instruction="Choose a CSV file, or drop it here" clearFileLabel="Remove the file" aria-invalid={invalid || undefined} aria-describedby="file-error"/>;What your application provides#
An instruction that names both ways in, and the name of the remove button, translated.
The check of the file.
acceptfilters the picker only; a dropped file and a picker set to "all files" bypass it, as the example shows with a non-CSV file.The error below the field, and the description of what is accepted.
id lands on the file input and class on the box.
Accessibility and keyboard#
One tab stop for the field, and one for the remove button once a file is chosen.
The instruction names the field; a second
Fieldwould give it two names.Label
API#
Import from @workspace/
Props
- Type
string
Accessible name of the button that releases the chosen file again.
- Type
string
Visible instruction in the box, and at the same time the accessible name of the file input: the <label> around it links the two.
Supplied translated and required; active- does not translate.
The text names both input paths. Dragging is a supplement and never the only route, so an instruction that only says "drag a file here" leaves keyboard and screen-reader users without guidance.
- Type
string
File types the field offers, as an accept value.
This is a filter in the file picker and not validation: the user can bypass that filter in every operating system. The substantive check stays the caller's schema. What the restriction says in human language belongs in the field's <Field; this component does not write a second text over it.
- Type
boolean
Turns off the field, the clear button and dropping at once.
- Type
Ref<HTMLDivElement>
The box element.
Events
Called by the component when something happens.
- Type
(file: File | null) => void
Receives the chosen or dropped file, or null when it is cleared.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.