Skip to content

Commit 9b6ae79

Browse files
committed
feat: do actual WithDragAndDropUpload container styling
1 parent 47f7e13 commit 9b6ae79

11 files changed

Lines changed: 113 additions & 55 deletions

File tree

examples/vite/src/App.tsx

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
ChannelSort,
66
LocalMessage,
77
TextComposerMiddleware,
8-
Event,
98
createCommandInjectionMiddleware,
109
createDraftCommandInjectionMiddleware,
1110
createActiveCommandGuardMiddleware,
@@ -28,6 +27,7 @@ import {
2827
Window,
2928
WithComponents,
3029
ReactionsList,
30+
WithDragAndDropUpload,
3131
} from 'stream-chat-react';
3232
import { createTextComposerEmojiMiddleware, EmojiPicker } from 'stream-chat-react/emojis';
3333
import { init, SearchIndex } from 'emoji-mart';
@@ -38,6 +38,14 @@ import { useAppSettingsState } from './AppSettings';
3838

3939
init({ data });
4040

41+
const parseUserIdFromToken = (token: string) => {
42+
const [, payload] = token.split('.');
43+
44+
if (!payload) throw new Error('Token is missing');
45+
46+
return JSON.parse(atob(payload))?.user_id;
47+
};
48+
4149
const apiKey = import.meta.env.VITE_STREAM_API_KEY;
4250
const token =
4351
new URLSearchParams(window.location.search).get('token') ||
@@ -79,7 +87,7 @@ const useUser = () => {
7987
}, [userId]);
8088

8189
const tokenProvider = useCallback(() => {
82-
return token
90+
return token && userId === parseUserIdFromToken(token)
8391
? Promise.resolve(token)
8492
: fetch(
8593
`https://pronto.getstream.io/api/auth/create-token?environment=shared-chat-redesign&user_id=${userId}`,
@@ -190,18 +198,22 @@ const App = () => {
190198
additionalChannelSearchProps={{ searchForChannels: true }}
191199
/>
192200
<Channel>
193-
<Window>
194-
<ChannelHeader Avatar={ChannelAvatar} />
195-
<MessageList returnAllReadData />
196-
<AIStateIndicator />
197-
<MessageInput
198-
focus
199-
audioRecordingEnabled
200-
maxRows={10}
201-
asyncMessagesMultiSendEnabled
202-
/>
203-
</Window>
204-
<Thread virtualized />
201+
<WithDragAndDropUpload>
202+
<Window>
203+
<ChannelHeader Avatar={ChannelAvatar} />
204+
<MessageList returnAllReadData />
205+
<AIStateIndicator />
206+
<MessageInput
207+
focus
208+
audioRecordingEnabled
209+
maxRows={10}
210+
asyncMessagesMultiSendEnabled
211+
/>
212+
</Window>
213+
</WithDragAndDropUpload>
214+
<WithDragAndDropUpload className='str-chat__dropzone-root--thread'>
215+
<Thread virtualized />
216+
</WithDragAndDropUpload>
205217
</Channel>
206218
</ChatView.Channels>
207219
<ChatView.Threads>

examples/vite/src/index.scss

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,18 @@ body {
9090
//max-width: none;
9191
}
9292

93+
.str-chat__dropzone-root--thread,
9394
.str-chat__thread-list-container,
9495
.str-chat__thread-container {
95-
flex: 0 0 360px;
96+
//flex: 0 0 360px;
9697
max-width: 360px;
9798
}
9899

99100
.str-chat__chat-view__threads {
101+
.str-chat__dropzone-root--thread,
100102
.str-chat__thread-container {
101103
flex: 1 1 auto;
102-
min-width: 360px;
104+
//min-width: 360px;
103105
max-width: none;
104106
}
105107
}
@@ -119,7 +121,7 @@ body {
119121
}
120122
}
121123

122-
@container (max-width: 760px) {
124+
@container (max-width: 860px) {
123125
.str-chat__channel-list,
124126
.str-chat__chat-view__selector {
125127
display: none;

examples/vite/src/stream-imports-layout.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
@use 'stream-chat-react/dist/scss/v2/common/CircleFAButton/CircleFAButton-layout';
1818
//@use 'stream-chat-react/dist/scss/v2/Dialog/Dialog-layout';
1919
//@use 'stream-chat-react/dist/scss/v2/DragAndDropContainer/DragAndDropContainer-layout';
20-
@use 'stream-chat-react/dist/scss/v2/DropzoneContainer/DropzoneContainer-layout'; // X
20+
//@use 'stream-chat-react/dist/scss/v2/DropzoneContainer/DropzoneContainer-layout'; // X
2121
//@use 'stream-chat-react/dist/scss/v2/EditMessageForm/EditMessageForm-layout';
2222
//@use 'stream-chat-react/dist/scss/v2/Form/Form-layout';
2323
@use 'stream-chat-react/dist/scss/v2/ImageCarousel/ImageCarousel-layout';

examples/vite/src/stream-imports-theme.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
@use 'stream-chat-react/dist/scss/v2/ChannelSearch/ChannelSearch-theme';
1616
//@use 'stream-chat-react/dist/scss/v2/Dialog/Dialog-theme';
1717
//@use 'stream-chat-react/dist/scss/v2/DragAndDropContainer/DragAndDropContainer-theme';
18-
@use 'stream-chat-react/dist/scss/v2/DropzoneContainer/DropzoneContainer-theme';
18+
//@use 'stream-chat-react/dist/scss/v2/DropzoneContainer/DropzoneContainer-theme';
1919
//@use 'stream-chat-react/dist/scss/v2/Form/Form-theme';
2020
//@use 'stream-chat-react/dist/scss/v2/Icon/Icon-theme';
2121
@use 'stream-chat-react/dist/scss/v2/ImageCarousel/ImageCarousel-theme';

src/components/Channel/Channel.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ import {
8888
} from '../Attachment/attachment-sizing';
8989
import { useSearchFocusedMessage } from '../../experimental/Search/hooks';
9090
import { WithAudioPlayback } from '../AudioPlayback';
91-
import { WithDragAndDropUpload } from '../MessageInput';
9291

9392
export type ChannelProps = {
9493
/** Custom handler function that runs when the active channel has unread messages and the app is running on a separate browser tab */
@@ -1157,9 +1156,7 @@ const ChannelInner = (
11571156
<ChannelActionProvider value={channelActionContextValue}>
11581157
<TypingProvider value={typingContextValue}>
11591158
<WithAudioPlayback allowConcurrentPlayback={allowConcurrentAudioPlayback}>
1160-
<WithDragAndDropUpload className={clsx(chatContainerClass)} component='div'>
1161-
{children}
1162-
</WithDragAndDropUpload>
1159+
<div className={clsx(chatContainerClass)}>{children}</div>
11631160
</WithAudioPlayback>
11641161
</TypingProvider>
11651162
</ChannelActionProvider>

src/components/MessageInput/styling/DragAndDropContainer.scss renamed to src/components/DragAndDrop/styling/DragAndDropContainer.scss

File renamed without changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@use "DragAndDropContainer";

src/components/MessageInput/WithDragAndDropUpload.tsx

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { useMessageInputContext, useTranslationContext } from '../../context';
88
import { useAttachmentManagerState, useMessageComposer } from './hooks';
99
import { useStateStore } from '../../store';
1010
import { useIsCooldownActive } from './hooks/useIsCooldownActive';
11+
import { IconFileArrowLeftIn } from '../Icons';
1112

1213
const DragAndDropUploadContext = React.createContext<{
1314
subscribeToDrop: ((fn: (files: File[]) => void) => () => void) | null;
@@ -123,34 +124,35 @@ export const WithDragAndDropUpload = ({
123124
// nested WithDragAndDropUpload components render wrappers without functionality
124125
// (MessageInputFlat has a default WithDragAndDropUpload)
125126
if (dragAndDropUploadContext.subscribeToDrop !== null) {
126-
return React.createElement(Component, { className }, children);
127+
return <Component className={className}>{children}</Component>;
127128
}
128129

129130
const rootClassName = clsx('str-chat__dropzone-root', className);
130131

131-
const overlay = isDragActive
132-
? React.createElement(
133-
'div',
134-
{
135-
className: clsx('str-chat__dropzone-container', {
136-
'str-chat__dropzone-container--not-accepted': isDragReject,
137-
}),
138-
role: 'presentation',
139-
},
140-
isDragReject
141-
? React.createElement('p', null, t('Some of the files will not be accepted'))
142-
: React.createElement('p', null, t('Drag your files here')),
143-
)
144-
: null;
145-
146-
return React.createElement(
147-
DragAndDropUploadContext.Provider,
148-
{ value: { subscribeToDrop } },
149-
React.createElement(
150-
Component,
151-
getRootProps({ className: rootClassName, style }),
152-
overlay,
153-
children,
154-
),
132+
return (
133+
<DragAndDropUploadContext.Provider value={{ subscribeToDrop }}>
134+
<Component {...getRootProps({ className: rootClassName, style })}>
135+
{isDragActive && (
136+
<div
137+
className={clsx('str-chat__dropzone-container', {
138+
'str-chat__dropzone-container--not-accepted': isDragReject,
139+
})}
140+
role='presentation'
141+
>
142+
<div className='str-chat__dropzone-container__content'>
143+
{isDragReject ? (
144+
<p>{t('Some of the files will not be accepted')}</p>
145+
) : (
146+
<>
147+
<IconFileArrowLeftIn />
148+
<p>{t('Drag your files here')}</p>
149+
</>
150+
)}
151+
</div>
152+
</div>
153+
)}
154+
{children}
155+
</Component>
156+
</DragAndDropUploadContext.Provider>
155157
);
156158
};
Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,65 @@
1-
// Full-screen drop overlay: root must be positioned so overlay fills it.
1+
.str-chat {
2+
/* The text/icon color of the dropzone container */
3+
--str-chat__dropzone-container-color: var(--text-primary);
4+
5+
/* The background color of the dropzone container */
6+
--str-chat__dropzone-container-background-color: var(--background-core-overlay-light);
7+
8+
/* The backdrop filter applied to the dropzone container */
9+
--str-chat__dropzone-container-backdrop-filter: blur(3.5px);
10+
}
11+
212
.str-chat__dropzone-root {
313
position: relative;
14+
min-height: 0;
15+
min-width: 0;
16+
max-width: 100%;
17+
max-height: 100%;
18+
flex: 1;
19+
}
20+
21+
// When wrapper has no content (e.g. Thread returns null when closed), take no space — keeps wrapper mounted to avoid remounts.
22+
.str-chat__dropzone-root:empty {
23+
display: none;
424
}
525

6-
// Overlay fills the entire drop root (message view).
726
.str-chat__dropzone-container {
8-
inset: 0;
27+
display: flex;
28+
align-items: center;
29+
justify-content: center;
930
position: absolute;
31+
inset: 0;
32+
z-index: 5;
33+
background-color: var(--str-chat__dropzone-container-background-color);
34+
color: var(--str-chat__dropzone-container-color);
35+
backdrop-filter: var(--str-chat__dropzone-container-backdrop-filter);
36+
font: var(--str-chat__heading-sm-text);
37+
38+
.str-chat__dropzone-container__content {
39+
display: flex;
40+
flex-direction: column;
41+
align-items: center;
42+
gap: var(--spacing-xs, 8px);
43+
}
44+
45+
svg {
46+
height: 32px;
47+
width: 32px;
48+
}
49+
50+
p {
51+
margin: unset;
52+
53+
}
1054
}
1155

1256
// When backdrop-filter is not supported, use a dimmed background only (no blur).
1357
@supports not (backdrop-filter: blur(1px)) {
1458
.str-chat__dropzone-container {
1559
backdrop-filter: none;
1660
background-color: var(
17-
--str-chat__dropzone-container-background-color-fallback,
18-
rgba(0, 0, 0, 0.4)
61+
--str-chat__dropzone-container-background-color-fallback,
62+
rgba(0, 0, 0, 0.4)
1963
);
2064
}
21-
}
65+
}

src/components/MessageInput/styling/index.scss

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
@use 'AttachmentPreviewThumbnail';
33
@use 'AttachmentSelector';
44
@use 'CommandChip';
5-
@use 'DragAndDropContainer';
65
@use 'DropzoneContainer';
76
@use 'CommandsMenu';
87
@use 'LinkPreviewList';

0 commit comments

Comments
 (0)