A Dropzone component built with shadcn/ui, react-dropzone, Yet Another React Lightbox and React Query written in Typescript for a Next.Js App.
Dropzone
This Dropzone follows a decoupled component design pattern and uses separate logic hooks for improved flexibility and scalability. It’s designed to integrate seamlessly with shadcn’s form system, which is built on top of React Hook Form and Zod.
Examples
Basic
Although it is meant to built for shadcn form system, you could implement it as basic as possible like in this example. Just use react useState hooks to manage your files and errors properly.
Multiple
Unlike many basic implementations that follow a success or nothing pattern, this Dropzone was designed to perform per-file validation, accepting the ones that pass and showing clear error feedback for the ones that don’t. Try dropping both valid and invalid files — you’ll see what I mean.
Disable
You could choose how the dropzone behaves when the file limit is reached based on your use case and still adjust it to your will. There are 3 options that are accommodated in this component and this is an example if you choose disable as your default onLimitReached option.
Custom
Since it’s designed with decoupled design pattern, you could customize it all you want and make it your own as per your own use case. This is possible due to the safe internal API exposure to be used in the form layer to make a edge cases behavior or interfaces for this component.
Document
It also accepts document type file like .pdf utilizing browser’s built-in preview capability to make it lighter and more versatile to use. No further configuration needed, just alter the accept property and you’re good to go.
Video
What i like about YERL is that it also comes with video preview plugin that you could plug and play as per your own use case that makes this dropzone compatible with video-type media file input.
Here’s a sneak peek at the implementation.
<FormField
control={control}
name='images'
render={({ field: { value, onChange, ref: _, ...field } }) => (
<FormItem>
<FormLabel></FormLabel>
<Dropzone
value={value}
onChange={onChange}
config={{ accept: {}, maxSize }}
uploadOptions={{
onDrop: (accepted, rejected) => {},
onError: (errors) => {},
}}
>
<DropzoneRoot>
<FormControl>
<DropzoneInput {...field} />
</FormControl>
<DropzoneArea>
<DropzoneIcon></DropzoneIcon>
<DropzoneText></DropzoneText>
<DropzoneDetail></DropzoneDetail>
</DropzoneArea>
</DropzoneRoot>
<DropzonePreviewList />
</Dropzone>
<FormDescription></FormDescription>
<FormMessage />
</FormItem>
)}
/>
Extra
You can also limit users’s input options like in this example to click-only with the help of react-dropzone’s curated properties that are already passed in this component’s custom hooks to be altered as you wished.
Bucket Integration
Last but not least, this Dropzone comes preconfigured to work with Google Cloud Storage using signed policies for uploads. Just update the env example file based on your bucket configuration and you’re good to go.