WithDragAndDropUpload
WithDragAndDropUpload makes an area take dropped files and upload them to the composers inside it. The composer UI already wraps itself in one; wrap a larger area, such as a whole channel, to take drops there. Drop files on a larger area explains how it fits with uploads.
Best practices
- Render it inside a
Channelor aThread. It reads the composer's upload settings from there, and throws outside both. - Wrap a channel and a thread separately. Files dropped on a wrapper go to every composer inside it, so a wrapper around both uploads each file twice.
- Don't nest wrappers to add drop areas: only the outermost one takes drops. A wrapper inside another renders only its element, with its
classNamebut without itsstyle. - Set the accepted file types in the composer configuration,
attachments.acceptedFiles. TheacceptedFilesprop has no effect. - To change the "Drag your files here" overlay, style
.str-chat__dropzone-container, or translatemessageComposer.dragDropUpload.dragFiles.textandmessageComposer.dragDropUpload.someFilesNotAccepted.text. TheFileDragAndDropContentoverride key has no effect: the wrapper rendersFileDragAndDropContentdirectly.
Basic usage
import type {
Channel as StreamChannel,
Thread as StreamThread,
} from "stream-chat";
import {
Channel,
ChannelHeader,
MessageComposer,
MessageList,
Thread,
ThreadHeader,
WithDragAndDropUpload,
} from "stream-chat-react";
export const ChannelAndThread = ({
channel,
thread,
}: {
channel: StreamChannel;
thread?: StreamThread;
}) => (
<>
<Channel channel={channel}>
<WithDragAndDropUpload className="channel-drop-zone" component="section">
<ChannelHeader />
<MessageList />
<MessageComposer />
</WithDragAndDropUpload>
</Channel>
{thread && (
<Thread thread={thread}>
<WithDragAndDropUpload className="thread-drop-zone" component="section">
<ThreadHeader />
<MessageList />
<MessageComposer />
</WithDragAndDropUpload>
</Thread>
)}
</>
);A file dropped anywhere in the channel's section goes to the channel's composer, and one dropped in the thread's goes to the thread's. The composer's own wrapper sits inside each, so it renders only its element.
The wrapper renders its element with the class str-chat__dropzone-root, which the SDK's stylesheet gives position: relative and flex: 1. Directly inside Channel, it becomes the channel's content column, a flex column. While files are dragged over it, it shows .str-chat__dropzone-container over its content: "Drag your files here", or "Some of the files will not be accepted" when a dragged file type isn't accepted.
It takes the file types from attachments.acceptedFiles of the composer around it, and takes several files at once when attachments.maxNumberOfFilesPerMessage is more than 1. Outside a composer, it takes drops even while uploads aren't allowed; each composer's AttachmentManager.uploadFiles() then applies the limits. The composer's own wrapper turns off during a slow-mode cooldown and when the user can't upload.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
children |
ReactNode |
The area that takes drops. | |
className |
string |
Added to the element, next to str-chat__dropzone-root. |
|
component |
React.ElementType |
"div" |
The element to render. |
style |
React.CSSProperties |
Inline styles for the element. A wrapper inside another doesn't apply them. | |
acceptedFiles |
string[] |
No effect. The accepted types come from the composer configuration, attachments.acceptedFiles. |
FileDragAndDropContent, the overlay's content, is exported too. It takes one prop, isDragRejected: boolean, which shows the "not accepted" text.