Skip to content

File Dropzone

FileDropzone takes files dropped onto it, and is also a button that opens the file picker. Drop an image on it, or press it:

No file yet

FileDropzoneDemo.tsx
import { Paragraph, Text, View } from '@hozo/core'
import { FileDropzone } from '@hozo/ui'
import { useState } from 'react'
export function FileDropzoneDemo() {
const [message, setMessage] = useState('No file yet')
return (
<View className="w-full max-w-md gap-3">
<FileDropzone
accessibilityLabel="Upload a photo"
accept={['image/png', 'image/jpeg']}
maxSize={5_000_000}
onFilesSelected={(files) => setMessage(`Chosen: ${files.map((f) => f.name).join(', ')}`)}
onRejected={(rejections) =>
setMessage(`Refused: ${rejections.map((r) => r.reason).join(', ')}`)
}
>
<Text className="font-semibold text-hozo-text">Drop a photo here</Text>
<Text className="text-sm text-hozo-text-body">or press to choose one, up to 5 MB</Text>
</FileDropzone>
<Paragraph className="text-sm text-hozo-text-body">{message}</Paragraph>
</View>
)
}
  • A button first. Dragging has no keyboard or screen-reader equivalent, so the zone is a real <button>, and Enter and Space open the picker. The drop is a shortcut on top of it.
  • accept, maxSize, minSize, multiple and maxFiles are the rules. Files that break one go to onRejected with a reason, and the rest go to onFilesSelected.
  • What was added and what was refused is announced in one sentence, such as “a.gif is not an accepted kind of file”, so a refusal is not only a red line a reader cannot see.
  • accessibilityLabel names the button. children are what it shows.