Merge pull request #3791 from Klauswk/FixUserDropDown

Fix user drop down - HTML5 Issue #3764
This commit is contained in:
Anton Georgiev 2017-04-11 16:00:21 -04:00 committed by GitHub
commit 5d75b79372

View File

@ -81,6 +81,9 @@ class UserListItem extends Component {
this.state = {
isActionsOpen: false,
dropdownOffset: 0,
dropdownDirection: 'top',
dropdownVisible: false,
};
this.handleScroll = this.handleScroll.bind(this);
@ -134,21 +137,82 @@ class UserListItem extends Component {
]);
}
componentDidUpdate(prevProps, prevState) {
this.checkDropdownDirection();
}
/**
* Check if the dropdown is visible, if so, check if should be draw on top or bottom direction.
*/
checkDropdownDirection() {
if (this.isDropdownActivedByUser()) {
const dropdown = findDOMNode(this.refs.dropdown);
const dropdownTrigger = dropdown.children[0];
const dropdownContent = dropdown.children[1];
const scrollContainer = dropdown.parentElement.parentElement;
let nextState = {
dropdownVisible: true,
};
const isDropdownVisible =
this.checkIfDropdownIsVisible(dropdownContent.offsetTop, dropdownContent.offsetHeight);
if (!isDropdownVisible) {
const offsetPageTop =
(dropdownTrigger.offsetTop + dropdownTrigger.offsetHeight - scrollContainer.scrollTop);
nextState.dropdownOffset = window.innerHeight - offsetPageTop;
nextState.dropdownDirection = 'bottom';
}
this.setState(nextState);
}
}
/**
* Check if the dropdown is visible and is opened by the user
*
* @return True if is visible and opened by the user.
*/
isDropdownActivedByUser() {
const { isActionsOpen, dropdownVisible } = this.state;
return isActionsOpen && !dropdownVisible;
}
/**
* Return true if the content fit on the screen, false otherwise.
*
* @param {number} contentOffSetTop
* @param {number} contentOffsetHeight
* @return True if the content fit on the screen, false otherwise.
*/
checkIfDropdownIsVisible(contentOffSetTop, contentOffsetHeight) {
return (contentOffSetTop + contentOffsetHeight) < window.innerHeight;
}
onActionsShow() {
const dropdown = findDOMNode(this.refs.dropdown);
const scrollContainer = dropdown.parentElement.parentElement;
const dropdownTrigger = dropdown.children[0];
this.setState({
contentTop: `${dropdown.offsetTop - dropdown.parentElement.parentElement.scrollTop}px`,
isActionsOpen: true,
active: true,
dropdownVisible: false,
dropdownOffset: dropdownTrigger.offsetTop - scrollContainer.scrollTop,
dropdownDirection: 'top',
});
findDOMNode(this).parentElement.addEventListener('scroll', this.handleScroll, false);
scrollContainer.addEventListener('scroll', this.handleScroll, false);
}
onActionsHide() {
this.setState({
active: false,
isActionsOpen: false,
dropdownVisible: false,
});
findDOMNode(this).parentElement.removeEventListener('scroll', this.handleScroll, false);
@ -161,7 +225,7 @@ class UserListItem extends Component {
let userItemContentsStyle = {};
userItemContentsStyle[styles.userItemContentsCompact] = compact;
userItemContentsStyle[styles.active] = this.state.active;
userItemContentsStyle[styles.active] = this.state.isActionsOpen;
return (
<li
@ -181,7 +245,7 @@ class UserListItem extends Component {
let actions = this.getAvailableActions();
let contents = (
<div tabIndex={0} className={styles.userItemContents}>
<UserAvatar user={user}/>
<UserAvatar user={user} />
{this.renderUserName()}
{this.renderUserIcons()}
</div>
@ -191,10 +255,12 @@ class UserListItem extends Component {
return contents;
}
const { dropdownOffset, dropdownDirection, dropdownVisible, } = this.state;
return (
<Dropdown
isOpen={this.state.isActionsOpen}
ref="dropdown"
isOpen={this.state.isActionsOpen}
onShow={this.onActionsShow}
onHide={this.onActionsHide}
className={styles.dropdown}>
@ -203,10 +269,11 @@ class UserListItem extends Component {
</DropdownTrigger>
<DropdownContent
style={{
top: this.state.contentTop,
visibility: dropdownVisible ? 'visible' : 'hidden',
[dropdownDirection]: `${dropdownOffset}px`,
}}
className={styles.dropdownContent}
placement="right top">
placement={`right ${dropdownDirection}`}>
<DropdownList>
{
@ -216,7 +283,7 @@ class UserListItem extends Component {
key={_.uniqueId('action-header')}
label={user.name}
style={{ fontWeight: 600 }}
defaultMessage={user.name}/>),
defaultMessage={user.name} />),
(<DropdownListSeparator key={_.uniqueId('action-separator')} />),
].concat(actions)
}
@ -295,16 +362,16 @@ class UserListItem extends Component {
{
user.isSharingWebcam ?
<span className={styles.userIconsContainer}>
<Icon iconName='video'/>
<Icon iconName='video' />
</span>
: null
}
{
audioChatIcon ?
<span className={cx(audioIconClassnames)}>
<Icon iconName={audioChatIcon}/>
</span>
: null
<span className={cx(audioIconClassnames)}>
<Icon iconName={audioChatIcon} />
</span>
: null
}
</div>
);