Skip to content

Commit ba65752

Browse files
authored
feat: adjust vertical and horizontal message spacing (#2954)
BREAKING CHANGE: remove props endOfGroup, firstOfGroup and groupedByUser from MessageProps as their purpose is unknown and message grouping should be done by Message prop groupStyles
1 parent 256d862 commit ba65752

20 files changed

Lines changed: 393 additions & 152 deletions

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
//@use 'stream-chat-react/dist/scss/v2/MessageActionsBox/MessageActionsBox-layout';
3131
//@use 'stream-chat-react/dist/scss/v2/MessageBouncePrompt/MessageBouncePrompt-layout';
3232
//@use 'stream-chat-react/dist/scss/v2/MessageInput/MessageInput-layout'; // X
33-
@use 'stream-chat-react/dist/scss/v2/MessageList/MessageList-layout';
34-
@use 'stream-chat-react/dist/scss/v2/MessageList/VirtualizedMessageList-layout';
33+
//@use 'stream-chat-react/dist/scss/v2/MessageList/MessageList-layout';
34+
//@use 'stream-chat-react/dist/scss/v2/MessageList/VirtualizedMessageList-layout';
3535
// @use 'stream-chat-react/dist/scss/v2/MessageReactions/MessageReactions-layout';
3636
@use 'stream-chat-react/dist/scss/v2/MessageReactions/MessageReactionsSelector-layout';
3737
//@use 'stream-chat-react/dist/scss/v2/Modal/Modal-layout';

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
//@use 'stream-chat-react/dist/scss/v2/Message/Message-theme';
2525
//@use 'stream-chat-react/dist/scss/v2/MessageActionsBox/MessageActionsBox-theme';
2626
//@use 'stream-chat-react/dist/scss/v2/MessageBouncePrompt/MessageBouncePrompt-theme';
27-
@use 'stream-chat-react/dist/scss/v2/MessageList/MessageList-theme';
28-
@use 'stream-chat-react/dist/scss/v2/MessageList/VirtualizedMessageList-theme';
27+
//@use 'stream-chat-react/dist/scss/v2/MessageList/MessageList-theme';
28+
//@use 'stream-chat-react/dist/scss/v2/MessageList/VirtualizedMessageList-theme';
2929
// @use 'stream-chat-react/dist/scss/v2/MessageReactions/MessageReactions-theme';
3030
@use 'stream-chat-react/dist/scss/v2/MessageReactions/MessageReactionsSelector-theme';
3131
//@use 'stream-chat-react/dist/scss/v2/Modal/Modal-theme';

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@
232232
"prettier-fix": "yarn prettier --write",
233233
"fix-staged": "lint-staged --config .lintstagedrc.fix.json --concurrent 1",
234234
"start": "tsc -p tsconfig.lib.json -w",
235-
"start:css": "sass --watch src/styling:dist/css src/plugins/Emojis/styling:dist/css",
235+
"start:css": "sass --watch src/styling:dist/css",
236236
"prepare": "husky install",
237237
"preversion": "yarn install",
238238
"test": "jest",

src/components/MediaRecorder/AudioRecorder/styling/AudioRecorder.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
display: flex;
55
align-items: center;
66
justify-content: center;
7-
max-width: 768px;
7+
max-width: var(--str-chat__message-composer-max-width);
88
width: 100%;
99
border-radius: var(--radius-3xl);
1010
border: 1px solid var(--border-core-default);

src/components/Message/Message.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ type MessageWithContextProps = Omit<MessageProps, MessagePropsToOmit> &
6363
const MessageWithContext = (props: MessageWithContextProps) => {
6464
const {
6565
canPin,
66-
groupedByUser,
6766
Message: propMessage,
6867
message,
6968
messageActions = Object.keys(MESSAGE_ACTIONS),
@@ -166,8 +165,7 @@ const MessageWithContext = (props: MessageWithContextProps) => {
166165

167166
return (
168167
<MessageProvider value={messageContextValue}>
169-
<MessageUIComponent groupedByUser={groupedByUser} />
170-
{/* TODO - remove prop in next major release, maintains VML backwards compatibility */}
168+
<MessageUIComponent />
171169
</MessageProvider>
172170
);
173171
};
@@ -263,10 +261,7 @@ export const Message = (props: MessageProps) => {
263261
closeReactionSelectorOnClick={closeReactionSelectorOnClick}
264262
deliveredTo={props.deliveredTo}
265263
disableQuotedMessages={props.disableQuotedMessages}
266-
endOfGroup={props.endOfGroup}
267-
firstOfGroup={props.firstOfGroup}
268264
formatDate={props.formatDate}
269-
groupedByUser={props.groupedByUser}
270265
groupStyles={props.groupStyles}
271266
handleAction={handleAction}
272267
handleDelete={handleDelete}

src/components/Message/MessageSimple.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const MessageSimpleWithContext = (props: MessageSimpleWithContextProps) => {
6161
onUserClick,
6262
onUserHover,
6363
renderText,
64+
showAvatar = 'incoming',
6465
threadList,
6566
} = props;
6667
const { client } = useChatContext('MessageSimple');
@@ -152,6 +153,12 @@ const MessageSimpleWithContext = (props: MessageSimpleWithContextProps) => {
152153
'str-chat__message--highlighted': highlighted,
153154
'str-chat__message--is-emoji-only': textHasEmojisOnly,
154155
'str-chat__message--pinned': message.pinned,
156+
'str-chat__message--with-avatar': (() => {
157+
if (!message.user) return false;
158+
if (showAvatar === 'incoming') return !isMyMessage();
159+
if (showAvatar === 'outgoing') return isMyMessage();
160+
return showAvatar;
161+
})(),
155162
'str-chat__message--with-reactions': hasReactions,
156163
'str-chat__message-send-can-be-retried':
157164
message?.status === 'failed' && message?.error?.status !== 403,

src/components/Message/styling/Message.scss

Lines changed: 77 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,28 @@
8787
--str-chat__message-with-attachment-max-width: calc(var(--str-chat__spacing-px) * 300);
8888
}
8989

90+
/* Make spaces between message groups */
91+
.str-chat__li--top {
92+
padding-block-start: var(--spacing-xs);
93+
padding-block-end: var(--spacing-xxxs);
94+
}
95+
96+
.str-chat__li--bottom {
97+
padding-block-start: var(--spacing-xxxs);
98+
padding-block-end: var(--spacing-xs);
99+
}
100+
101+
.str-chat__li--middle {
102+
padding-block: var(--spacing-xxxs);
103+
}
104+
105+
.str-chat__li--single {
106+
padding-block: var(--spacing-xs);
107+
}
108+
90109
.str-chat__message {
91110
--str-chat-message-options-size: calc(3 * var(--str-chat__message-options-button-size));
111+
padding-inline: var(--str-chat__message-composer-padding);
92112

93113
&.str-chat__message-without-touch-support {
94114
--str-chat-message-options-size: calc(
@@ -214,12 +234,45 @@
214234

215235
.str-chat__message-reminder {
216236
grid-area: message-reminder;
217-
padding-block: var(--str-chat__spacing-2) var(--str-chat__spacing-0_5);
237+
padding-block: var(--spacing-xxs);
218238
margin: 0;
219239
@include utils.component-layer-overrides('message-reminder');
220240
font: var(--str-chat__caption-medium-text);
221241
}
222242

243+
@mixin message-grid-no-avatar {
244+
grid-template-areas:
245+
'pin-indicator'
246+
'message-reminder'
247+
'message'
248+
'translation-notice'
249+
'custom-metadata'
250+
'metadata';
251+
grid-template-columns: 1fr;
252+
}
253+
254+
@mixin message-grid-other-with-avatar {
255+
grid-template-areas:
256+
'. pin-indicator'
257+
'. message-reminder'
258+
'avatar message'
259+
'avatar translation-notice'
260+
'avatar custom-metadata'
261+
'avatar metadata';
262+
grid-template-columns: auto 1fr;
263+
}
264+
265+
@mixin message-grid-me-with-avatar {
266+
grid-template-areas:
267+
'pin-indicator .'
268+
'message-reminder .'
269+
'message avatar'
270+
'translation-notice avatar'
271+
'custom-metadata avatar'
272+
'metadata avatar';
273+
grid-template-columns: 1fr auto;
274+
}
275+
223276
.str-chat__message-pin-indicator {
224277
grid-area: pin-indicator;
225278
padding-block: var(--spacing-xxs);
@@ -238,16 +291,17 @@
238291
}
239292

240293
&.str-chat__message--other {
241-
grid-template-areas:
242-
'. message-reminder'
243-
'avatar message'
244-
'avatar translation-notice'
245-
'avatar custom-metadata'
246-
'avatar metadata';
247294
column-gap: var(--str-chat__spacing-2);
248-
grid-template-columns: auto 1fr;
249295
justify-items: flex-start;
250296

297+
&.str-chat__message--with-avatar {
298+
@include message-grid-other-with-avatar;
299+
}
300+
301+
&:not(.str-chat__message--with-avatar) {
302+
@include message-grid-no-avatar;
303+
}
304+
251305
.str-chat__message-inner {
252306
.str-chat__message-reactions-host {
253307
justify-self: flex-start;
@@ -268,36 +322,25 @@
268322
}
269323

270324
&.str-chat__message--pinned.str-chat__message--other {
271-
grid-template-areas:
272-
'. pin-indicator'
273-
'. message-reminder'
274-
'avatar message'
275-
'avatar translation-notice'
276-
'avatar custom-metadata'
277-
'avatar metadata';
325+
@include message-grid-other-with-avatar;
278326
}
279327

280328
&.str-chat__message--pinned.str-chat__message--me {
281-
grid-template-areas:
282-
'pin-indicator .'
283-
'message-reminder .'
284-
'message avatar'
285-
'translation-notice avatar'
286-
'custom-metadata avatar'
287-
'metadata avatar';
329+
@include message-grid-me-with-avatar;
288330
}
289331

290332
&.str-chat__message--me {
291-
grid-template-areas:
292-
'message-reminder .'
293-
'message avatar'
294-
'translation-notice avatar'
295-
'custom-metadata avatar'
296-
'metadata avatar';
297333
column-gap: var(--str-chat__spacing-2);
298-
grid-template-columns: 1fr auto;
299334
justify-items: flex-end;
300335

336+
&.str-chat__message--with-avatar {
337+
@include message-grid-me-with-avatar;
338+
}
339+
340+
&:not(.str-chat__message--with-avatar) {
341+
@include message-grid-no-avatar;
342+
}
343+
301344
.str-chat__message-inner {
302345
.str-chat__message-reactions-host {
303346
justify-self: flex-end;
@@ -315,6 +358,7 @@
315358
}
316359
}
317360
}
361+
318362
}
319363

320364
&.str-chat__message--deleted {
@@ -335,7 +379,7 @@
335379
align-self: end;
336380
}
337381

338-
&.str-chat__message--me .str-chat__avatar:has(~ .str-chat__message-inner) {
382+
&:not(.str-chat__message--with-avatar) .str-chat__avatar {
339383
display: none;
340384
}
341385

@@ -660,36 +704,17 @@
660704
.str-chat__li--middle,
661705
.str-chat__li--top {
662706
.str-chat__message {
663-
// space below the message within a group
664-
padding-block-end: var(--spacing-xxs);
665-
666707
.str-chat__message-metadata {
667708
display: none;
668709
}
669710

670-
// > selector added to not hide sender of inline replies
671-
> .str-chat__message-sender-avatar {
711+
// Hide sender avatar in middle/top of group (only show on last message in group)
712+
> .str-chat__avatar {
672713
visibility: hidden;
673714
}
674715
}
675716
}
676717

677-
.str-chat__li--top,
678-
.str-chat__li--single {
679-
.str-chat__message {
680-
// space above the message group
681-
padding-block-start: var(--spacing-xs);
682-
}
683-
}
684-
685-
.str-chat__li--bottom,
686-
.str-chat__li--single {
687-
.str-chat__message {
688-
// space below the message group
689-
padding-block-end: var(--spacing-xs);
690-
}
691-
}
692-
693718
.str-chat__li--single,
694719
.str-chat__li--bottom {
695720
.str-chat__message--other {
@@ -729,7 +754,7 @@
729754
// Avatar display in message list
730755
.str-chat__li--top,
731756
.str-chat__li--middle {
732-
.str-chat__message > .str-chat__avatar {
757+
.str-chat__message.str-chat__message--with-avatar > .str-chat__avatar {
733758
visibility: hidden;
734759
pointer-events: none;
735760
}

src/components/Message/types.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ export type MessageProps = {
2626
deliveredTo?: UserResponse[];
2727
/** If true, disables the ability for users to quote messages, defaults to false */
2828
disableQuotedMessages?: boolean;
29-
/** When true, the message is the last one in a group sent by a specific user (only used in the `VirtualizedMessageList`) */
30-
endOfGroup?: boolean;
31-
/** When true, the message is the first one in a group sent by a specific user (only used in the `VirtualizedMessageList`) */
32-
firstOfGroup?: boolean;
3329
/** Override the default formatting of the date. This is a function that has access to the original date object, returns a string */
3430
formatDate?: (date: Date) => string;
3531
/** Function that returns the notification text to be displayed when a delete message request fails */
@@ -50,8 +46,6 @@ export type MessageProps = {
5046
getMuteUserSuccessNotification?: (user: UserResponse) => string;
5147
/** Function that returns the notification text to be displayed when a pin message request fails */
5248
getPinMessageErrorNotification?: (message: LocalMessage) => string;
53-
/** If true, group messages sent by each user (only used in the `VirtualizedMessageList`) */
54-
groupedByUser?: boolean;
5549
/** A list of styles to apply to this message, i.e. top, bottom, single */
5650
groupStyles?: GroupStyle[];
5751
/** Whether to highlight and focus the message on load */
@@ -88,6 +82,14 @@ export type MessageProps = {
8882
reactionDetailsSort?: ReactionSort;
8983
/** A list of users that have read this Message if the message is the last one and was posted by my user */
9084
readBy?: UserResponse[];
85+
/**
86+
* When set, the message uses the grid layout with an avatar column and shows the sender avatar.
87+
* - `true`: show for incoming and outgoing messages
88+
* - `'incoming'`: show only for incoming (other users') messages
89+
* - `'outgoing'`: show only for own (outgoing) messages
90+
* - `false` or omitted: no avatar column
91+
*/
92+
showAvatar?: boolean | 'incoming' | 'outgoing';
9193
/** Custom function to render message text content, defaults to the renderText function: [utils](https://github.com/GetStream/stream-chat-react/blob/master/src/utils.ts) */
9294
renderText?: (
9395
text?: string,

src/components/Message/utils.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,6 @@ export const areMessagePropsEqual = (
272272
const { message: nextMessage, Message: nextMessageUI } = nextProps;
273273

274274
if (prevMessageUI !== nextMessageUI) return false;
275-
if (prevProps.endOfGroup !== nextProps.endOfGroup) return false;
276275

277276
if (nextProps.showDetailedReactions !== prevProps.showDetailedReactions) {
278277
return false;

src/components/MessageInput/styling/MessageComposer.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
--str-chat__cooldown-border-inline-end: 0;
3737
--str-chat__cooldown-box-shadow: none;
3838
--str-chat__message-composer-max-width: 768px;
39+
--str-chat__message-composer-padding: var(--spacing-md);
3940

4041
.str-chat__message-composer-container {
4142
width: 100%;
@@ -44,7 +45,7 @@
4445
align-items: center;
4546
gap: var(--spacing-xs);
4647
justify-content: center;
47-
padding: var(--spacing-xs);
48+
padding: var(--str-chat__message-composer-padding);
4849
min-width: 0;
4950
}
5051

0 commit comments

Comments
 (0)