Skip to content

Commit 6ed6ace

Browse files
authored
Fix: Event leakage issues (#80)
* Block scrolling of body tag when pop-up components appear * Prevent unexpected scrolling when fetching messages * Add sample case for when chat app is smaller than the page size [UIKIT-1461](https://sendbird.atlassian.net/browse/UIKIT-1461) [UIKIT-1467](https://sendbird.atlassian.net/browse/UIKIT-1467)
1 parent cee7908 commit 6ed6ace

File tree

7 files changed

+53
-3
lines changed

7 files changed

+53
-3
lines changed

src/smart-components/App/stories/index.stories.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,24 @@ const CustomApp = () => {
379379

380380
export const customer1 = () => fitPageSize(<CustomApp />);
381381

382+
export const customer2 = () => (
383+
<div style={{ height: '2000px', width: '100vw', backgroundColor: 'gray', position: 'relative', display: 'flex', justifyContent: 'center'}}>
384+
<div style={{ height: '100vh', width: '90vw', position: 'relative', top: '200px' }}>
385+
<App
386+
appId={appId}
387+
userId={array[0]}
388+
nickname={array[0]}
389+
profileUrl={addProfile}
390+
showSearchIcon
391+
allowProfileEdit
392+
config={{ logLevel: 'all' }}
393+
queries={{}}
394+
replyType="QUOTE_REPLY"
395+
/>
396+
</div>
397+
</div>
398+
);
399+
382400
export const disableUserProfile = () => fitPageSize(
383401
<App
384402
showSearchIcon

src/smart-components/Conversation/components/ConversationScroll.jsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ export default class ConversationScroll extends Component {
5555
onScroll(([messages]) => {
5656
if (messages) {
5757
// https://github.com/scabbiaza/react-scroll-position-on-updating-dom
58+
// Set block to nearest to prevent unexpected scrolling from outer components
5859
try {
59-
first.scrollIntoView();
60+
first.scrollIntoView({ block: 'nearest' });
6061
} catch (error) {
6162
//
6263
}
@@ -71,7 +72,7 @@ export default class ConversationScroll extends Component {
7172
if (messages) {
7273
// https://github.com/scabbiaza/react-scroll-position-on-updating-dom
7374
try {
74-
last.scrollIntoView();
75+
last.scrollIntoView({ block: 'nearest' });
7576
} catch (error) {
7677
//
7778
}

src/ui/ContextMenu/index.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
@import '../../styles/variables';
22

3+
body.sendbird-emoji-list-pop-up,
4+
body.sendbird-menu-items-pop-up {
5+
overflow: hidden !important;
6+
}
7+
38
.sendbird__offline {
49
.sendbird-dropdown__menu .sendbird-dropdown__menu-item {
510
cursor: not-allowed;

src/ui/ContextMenu/items/EmojiListItems.jsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ import PropTypes from 'prop-types';
44

55
import SortByRow from '../../SortByRow';
66

7+
const EMOJI_LIST_POP_UP = 'sendbird-emoji-list-pop-up';
8+
79
export default class EmojiListItems extends Component {
810
constructor(props) {
911
super(props);
1012
this.reactionRef = React.createRef();
13+
this.rootForPopup = document.body;
1114
this.state = {
1215
reactionStyle: {},
1316
handleClickOutside: () => { },
@@ -18,11 +21,15 @@ export default class EmojiListItems extends Component {
1821
this.setupEvents();
1922
this.getBarPosition();
2023
this.showParent();
24+
// add className to body
25+
this.rootForPopup.className = `${EMOJI_LIST_POP_UP} ${this.rootForPopup.className}`;
2126
}
2227

2328
componentWillUnmount() {
2429
this.cleanUpEvents();
2530
this.hideParent();
31+
// remove className from body
32+
this.rootForPopup.className = this.rootForPopup.className.split(' ').filter((className) => className !== EMOJI_LIST_POP_UP).join(' ');
2633
}
2734

2835
showParent = () => {

src/ui/ContextMenu/items/MenuItems.jsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ import React, { Component } from 'react';
22
import { createPortal } from 'react-dom';
33
import PropTypes from 'prop-types';
44

5+
const MENU_ITEMS_POP_UP = 'sendbird-menu-items-pop-up';
6+
57
export default class MenuItems extends Component {
68
constructor(props) {
79
super(props);
810
this.menuRef = React.createRef();
11+
this.rootForPopup = document.body;
912
this.state = {
1013
menuStyle: {},
1114
handleClickOutside: () => { },
@@ -16,11 +19,15 @@ export default class MenuItems extends Component {
1619
this.setupEvents();
1720
this.getMenuPosition();
1821
this.showParent();
22+
// add className to body
23+
this.rootForPopup.className = `${MENU_ITEMS_POP_UP} ${this.rootForPopup.className}`;
1924
}
2025

2126
componentWillUnmount() {
2227
this.cleanUpEvents();
2328
this.hideParent();
29+
// remove className from body
30+
this.rootForPopup.className = this.rootForPopup.className.split(' ').filter((className) => className !== MENU_ITEMS_POP_UP).join(' ');
2431
}
2532

2633
showParent = () => {

src/ui/Modal/index.jsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useContext } from 'react';
1+
import React, { useContext, useEffect } from 'react';
22
import PropTypes from 'prop-types';
33
import { createPortal } from 'react-dom';
44

@@ -80,6 +80,14 @@ export default function Modal(props) {
8080
hideFooter,
8181
type,
8282
} = props;
83+
const { body } = document;
84+
useEffect(() => {
85+
body.className = `sendbird-modal-pop-up ${body.className}`;
86+
return () => {
87+
body.className = body.className.split(' ').filter((className) => className !== 'sendbird-modal-pop-up').join(' ');
88+
};
89+
}, []);
90+
8391
return createPortal((
8492
<div className="sendbird-modal">
8593
<div className="sendbird-modal__content">

src/ui/Modal/index.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,7 @@
6161
background-color: t(overlay-2);
6262
}
6363
}
64+
65+
body.sendbird-modal-pop-up {
66+
overflow: hidden !important;
67+
}

0 commit comments

Comments
 (0)