Skip to content

Commit 02bd9bb

Browse files
Another set of adjustments with demo
1 parent 72c2ef9 commit 02bd9bb

4 files changed

Lines changed: 181 additions & 104 deletions

File tree

examples/vite/src/App.tsx

Lines changed: 116 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { type PropsWithChildren, useCallback, useEffect, useMemo } from 'react';
1+
import {
2+
createContext,
3+
type PropsWithChildren,
4+
useCallback,
5+
useContext,
6+
useEffect,
7+
useMemo,
8+
useState,
9+
} from 'react';
210
import {
311
ChannelFilters,
412
ChannelOptions,
@@ -85,19 +93,44 @@ const useUser = () => {
8593
const CustomMessageReactions = (props: React.ComponentProps<typeof ReactionsList>) => {
8694
const { isMyMessage } = useMessageContext();
8795
const messageBelongsToCurrentUser = isMyMessage();
96+
const { visualStyle, verticalPosition, horizontalPosition } = useContext(TempCtx);
8897

8998
return (
9099
<ReactionsList
91100
{...props}
92-
horizontalPosition={messageBelongsToCurrentUser ? 'start' : 'end'}
93-
verticalPosition='top'
101+
horizontalPosition={
102+
horizontalPosition === 'end' && messageBelongsToCurrentUser
103+
? 'start'
104+
: horizontalPosition === 'start' && messageBelongsToCurrentUser
105+
? 'end'
106+
: horizontalPosition
107+
}
108+
verticalPosition={verticalPosition}
109+
visualStyle={visualStyle}
94110
/>
95111
);
96112
};
97113

114+
type TempCtxValue = {
115+
visualStyle: 'clustered' | 'segmented';
116+
verticalPosition: 'top' | 'bottom';
117+
horizontalPosition: 'start' | 'end';
118+
};
119+
const TempCtx = createContext<TempCtxValue>({
120+
visualStyle: 'clustered',
121+
verticalPosition: 'top',
122+
horizontalPosition: 'start',
123+
});
124+
98125
const App = () => {
99126
const { userId, tokenProvider } = useUser();
100127

128+
const [tempCtxValue, setTempCtxValue] = useState<TempCtxValue>({
129+
visualStyle: 'clustered',
130+
verticalPosition: 'top',
131+
horizontalPosition: 'start',
132+
});
133+
101134
const chatClient = useCreateChatClient({
102135
apiKey,
103136
tokenOrProvider: tokenProvider,
@@ -157,49 +190,86 @@ const App = () => {
157190
if (!chatClient) return <>Loading...</>;
158191

159192
return (
160-
<WithComponents
161-
overrides={{
162-
emojiSearchIndex: SearchIndex,
163-
EmojiPicker,
164-
ReactionsList: CustomMessageReactions,
165-
}}
166-
>
167-
<Chat client={chatClient} isMessageAIGenerated={isMessageAIGenerated}>
168-
<ChatView>
169-
<ChatView.Selector />
170-
<ChatView.Channels>
171-
<ChannelList
172-
Avatar={ChannelAvatar}
173-
filters={filters}
174-
options={options}
175-
sort={sort}
176-
showChannelSearch
177-
additionalChannelSearchProps={{ searchForChannels: true }}
178-
/>
179-
<Channel>
180-
<Window>
181-
<ChannelHeader Avatar={ChannelAvatar} />
182-
<MessageList returnAllReadData />
183-
<AIStateIndicator />
184-
<MessageInput
185-
focus
186-
audioRecordingEnabled
187-
maxRows={10}
188-
asyncMessagesMultiSendEnabled
189-
/>
190-
</Window>
191-
<Thread virtualized />
192-
</Channel>
193-
</ChatView.Channels>
194-
<ChatView.Threads>
195-
<ThreadList />
196-
<ChatView.ThreadAdapter>
197-
<Thread virtualized />
198-
</ChatView.ThreadAdapter>
199-
</ChatView.Threads>
200-
</ChatView>
201-
</Chat>
202-
</WithComponents>
193+
<TempCtx.Provider value={tempCtxValue}>
194+
<WithComponents
195+
overrides={{
196+
emojiSearchIndex: SearchIndex,
197+
EmojiPicker,
198+
ReactionsList: CustomMessageReactions,
199+
}}
200+
>
201+
<Chat client={chatClient} isMessageAIGenerated={isMessageAIGenerated}>
202+
<ChatView>
203+
<ChatView.Selector />
204+
<ChatView.Channels>
205+
<ChannelList
206+
Avatar={ChannelAvatar}
207+
filters={filters}
208+
options={options}
209+
sort={sort}
210+
showChannelSearch
211+
additionalChannelSearchProps={{ searchForChannels: true }}
212+
/>
213+
<Channel>
214+
<Window>
215+
<div style={{ display: 'flex', gap: 10, padding: 10 }}>
216+
<button
217+
onClick={() =>
218+
setTempCtxValue((prev) => ({
219+
...prev,
220+
visualStyle:
221+
prev.visualStyle === 'clustered' ? 'segmented' : 'clustered',
222+
}))
223+
}
224+
>
225+
Toggle Visual Style
226+
</button>
227+
<button
228+
onClick={() =>
229+
setTempCtxValue((prev) => ({
230+
...prev,
231+
verticalPosition:
232+
prev.verticalPosition === 'top' ? 'bottom' : 'top',
233+
}))
234+
}
235+
>
236+
Toggle Vertical Position
237+
</button>
238+
<button
239+
onClick={() =>
240+
setTempCtxValue((prev) => ({
241+
...prev,
242+
horizontalPosition:
243+
prev.horizontalPosition === 'start' ? 'end' : 'start',
244+
}))
245+
}
246+
>
247+
Toggle Horizontal Position
248+
</button>
249+
</div>
250+
<ChannelHeader Avatar={ChannelAvatar} />
251+
<MessageList returnAllReadData />
252+
<AIStateIndicator />
253+
<MessageInput
254+
focus
255+
audioRecordingEnabled
256+
maxRows={10}
257+
asyncMessagesMultiSendEnabled
258+
/>
259+
</Window>
260+
<Thread virtualized />
261+
</Channel>
262+
</ChatView.Channels>
263+
<ChatView.Threads>
264+
<ThreadList />
265+
<ChatView.ThreadAdapter>
266+
<Thread virtualized />
267+
</ChatView.ThreadAdapter>
268+
</ChatView.Threads>
269+
</ChatView>
270+
</Chat>
271+
</WithComponents>
272+
</TempCtx.Provider>
203273
);
204274
};
205275

src/components/Message/styling/Message.scss

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@
111111
.str-chat__message-bubble {
112112
background-color: transparent;
113113
overflow: visible;
114-
font-size: 64px;
115-
line-height: 64px;
114+
font-size: var(--size-64);
115+
line-height: 1;
116116
}
117117
}
118118
}
@@ -196,10 +196,10 @@
196196
grid-template-areas:
197197
'. message-reminder'
198198
'avatar message'
199-
'. replies'
200-
'. translation-notice'
201-
'. custom-metadata'
202-
'. metadata';
199+
'avatar replies'
200+
'avatar translation-notice'
201+
'avatar custom-metadata'
202+
'avatar metadata';
203203
column-gap: var(--str-chat__spacing-2);
204204
grid-template-columns: auto 1fr;
205205
justify-items: flex-start;
@@ -238,7 +238,7 @@
238238
grid-template-columns: auto;
239239
}
240240

241-
.str-chat__message-sender-avatar {
241+
.str-chat__avatar:has(~ .str-chat__message-inner) {
242242
grid-area: avatar;
243243
align-self: end;
244244
}
@@ -322,6 +322,7 @@
322322
}
323323

324324
&:has(.str-chat__message-reactions--top) {
325+
// maybe remove later
325326
}
326327

327328
&:has(.str-chat__message-reactions--bottom) {

src/components/Reactions/ReactionsList.tsx

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* eslint-disable sort-keys */
21
import React, { useState } from 'react';
32
import clsx from 'clsx';
43

@@ -55,6 +54,7 @@ export type ReactionsListProps = Partial<
5554
*/
5655
horizontalPosition?: 'start' | 'end' | null;
5756
verticalPosition?: 'top' | 'bottom' | null;
57+
visualStyle?: 'clustered' | 'segmented' | null;
5858
};
5959

6060
const UnMemoizedReactionsList = (props: ReactionsListProps) => {
@@ -68,6 +68,7 @@ const UnMemoizedReactionsList = (props: ReactionsListProps) => {
6868
reactionDetailsSort,
6969
sortReactionDetails,
7070
verticalPosition = 'top',
71+
visualStyle = 'clustered',
7172
...rest
7273
} = props;
7374

@@ -79,12 +80,13 @@ const UnMemoizedReactionsList = (props: ReactionsListProps) => {
7980
const { t } = useTranslationContext('ReactionsList');
8081
const { ReactionsListModal = DefaultReactionsListModal } = useComponentContext();
8182

82-
const handleReactionButtonClick = (reactionType: string) => {
83+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
84+
const handleReactionButtonClick = (reactionType: ReactionType) => {
8385
if (totalReactionCount > MAX_MESSAGE_REACTIONS_TO_FETCH) {
8486
return;
8587
}
8688

87-
setSelectedReactionType(reactionType as ReactionType);
89+
setSelectedReactionType(reactionType);
8890
};
8991

9092
if (!hasReactions) return null;
@@ -98,35 +100,36 @@ const UnMemoizedReactionsList = (props: ReactionsListProps) => {
98100
typeof horizontalPosition === 'string',
99101
[`str-chat__message-reactions--${verticalPosition}`]:
100102
typeof verticalPosition === 'string',
101-
'str-chat__message-reactions--clustered': true,
102-
'str-chat__message-reactions--segmented': false,
103+
[`str-chat__message-reactions--${visualStyle}`]:
104+
typeof visualStyle === 'string',
103105
})}
104106
role='figure'
105107
>
106108
<ul className='str-chat__message-reactions__list'>
107109
{existingReactions.map(
108110
({ EmojiComponent, reactionCount, reactionType }) =>
109111
EmojiComponent && (
110-
<li
111-
className={clsx('str-chat__message-reactions__list-item')}
112-
key={reactionType}
113-
>
112+
<li className='str-chat__message-reactions__list-item' key={reactionType}>
114113
<span className='str-chat__message-reactions__item-icon'>
115114
<EmojiComponent />
116115
</span>
117-
<span
118-
className='str-chat__message-reactions__item-count'
119-
data-testclass='reaction-list-reaction-count'
120-
>
121-
{reactionCount}
122-
</span>
116+
{visualStyle === 'segmented' && (
117+
<span
118+
className='str-chat__message-reactions__item-count'
119+
data-testclass='message-reactions-item-count'
120+
>
121+
{reactionCount}
122+
</span>
123+
)}
123124
</li>
124125
),
125126
)}
126127
</ul>
127-
<span className='str-chat__message-reactions__total-count'>
128-
{totalReactionCount}
129-
</span>
128+
{visualStyle === 'clustered' && (
129+
<span className='str-chat__message-reactions__total-count'>
130+
{totalReactionCount}
131+
</span>
132+
)}
130133
</div>
131134
{selectedReactionType !== null && (
132135
<ReactionsListModal

0 commit comments

Comments
 (0)