diff --git a/bigbluebutton-html5/client/main.html b/bigbluebutton-html5/client/main.html
index fe5209cf13a23c11cddf8928c3f726afd6fbe1eb..f494c9d887fd126452f8f29936130ad18b257168 100755
--- a/bigbluebutton-html5/client/main.html
+++ b/bigbluebutton-html5/client/main.html
@@ -56,6 +56,21 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
       border: 0;
     }
 
+    .set-z-index {
+      z-index: 15;
+      width: 100% !important;
+      height: 100% !important;
+    }
+
+    .remove-z-index {
+      z-index: 0;
+    }
+    /* .full-screen {
+      height: 100% !important;
+      width: 100% !important;
+      transform: translateX(0) translateY(0) translateZ(0) !important;
+    } */
+
     [hidden]:not([hidden="false"]) {
       display: none !important;
     }
@@ -73,6 +88,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 </head>
 <body style="background-color: #06172A">
   <div id="app" role="document"></div>
+  <span id="destination"></span>
   <audio id="remote-media" autoPlay="autoplay">
     <track kind="captions" /> {/* These captions are brought to you by eslint */}
   </audio>
diff --git a/bigbluebutton-html5/imports/ui/components/dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/dropdown/component.jsx
index 4183ae38cff6697594836c9583fea2feff0acafd..23bf500e1cd8513d87873dc554369fa61454c131 100644
--- a/bigbluebutton-html5/imports/ui/components/dropdown/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/dropdown/component.jsx
@@ -1,6 +1,8 @@
-import React, { Component } from 'react';
+import React, { Component, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import { findDOMNode } from 'react-dom';
+import { isMobile } from 'react-device-detect';
+import TetherComponent from 'react-tether';
 import cx from 'classnames';
 import { defineMessages, injectIntl, intlShape } from 'react-intl';
 import Button from '/imports/ui/components/button/component';
@@ -16,7 +18,7 @@ const intlMessages = defineMessages({
   },
 });
 
-const noop = () => {};
+const noop = () => { };
 
 const propTypes = {
   /**
@@ -51,6 +53,7 @@ const propTypes = {
   onShow: PropTypes.func,
   autoFocus: PropTypes.bool,
   intl: intlShape.isRequired,
+  tethered: PropTypes.bool,
 };
 
 const defaultProps = {
@@ -60,6 +63,16 @@ const defaultProps = {
   autoFocus: false,
   isOpen: false,
   keepOpen: null,
+  getContent: () => {},
+};
+
+const attachments = {
+  'right-bottom': 'bottom left',
+  'right-top': 'bottom left',
+};
+const targetAttachments = {
+  'right-bottom': 'bottom right',
+  'right-top': 'top right',
 };
 
 class Dropdown extends Component {
@@ -162,10 +175,24 @@ class Dropdown extends Component {
       className,
       intl,
       keepOpen,
+      tethered,
+      placement,
+      getContent,
       ...otherProps
     } = this.props;
 
     const { isOpen } = this.state;
+    
+    const placements = placement && placement.replace(' ', '-');
+    const test = isMobile ? {
+      width: '100%',
+      height: '100%',
+      transform: 'translateY(0)',
+    } : {
+      width: '',
+      height: '',
+      transform: '',
+    };
 
     let trigger = children.find(x => x.type === DropdownTrigger);
     let content = children.find(x => x.type === DropdownContent);
@@ -176,15 +203,20 @@ class Dropdown extends Component {
       dropdownToggle: this.handleToggle,
       dropdownShow: this.handleShow,
       dropdownHide: this.handleHide,
+      keepOpen,
     });
 
     content = React.cloneElement(content, {
-      ref: (ref) => { this.content = ref; },
+      ref: (ref) => {
+        getContent(ref);
+        this.content = ref;
+      },
       'aria-expanded': isOpen,
       dropdownIsOpen: isOpen,
       dropdownToggle: this.handleToggle,
       dropdownShow: this.handleShow,
       dropdownHide: this.handleHide,
+      keepOpen,
     });
 
     const showCloseBtn = (isOpen && keepOpen) || (isOpen && keepOpen === null);
@@ -199,18 +231,67 @@ class Dropdown extends Component {
         ref={(node) => { this.dropdown = node; }}
         tabIndex={-1}
       >
-        {trigger}
-        {content}
-        {showCloseBtn
-          ? (
-            <Button
-              className={styles.close}
-              label={intl.formatMessage(intlMessages.close)}
-              size="lg"
-              color="default"
-              onClick={this.handleHide}
-            />
-          ) : null}
+        {
+          tethered ?
+            (
+              <TetherComponent
+                style={{
+                  zIndex: isOpen ? 15 : '',
+                  ...test,
+                }}
+                attachment={
+                  isMobile ? 'middle bottom'
+                    : attachments[placements]
+                }
+                targetAttachment={
+                  isMobile ? ''
+                    : targetAttachments[placements]
+                }
+                constraints={[
+                  {
+                    to: 'scrollParent',
+                  },
+                ]}
+                renderTarget={ref => (
+                  <span ref={ref}>
+                    {trigger}
+                  </span>)}
+                renderElement={ref => (
+                  <div
+                    ref={ref}
+                  >
+                    {content}
+                    {showCloseBtn
+                      ? (
+                        <Button
+                          className={styles.close}
+                          label={intl.formatMessage(intlMessages.close)}
+                          size="lg"
+                          color="default"
+                          onClick={this.handleHide}
+                        />
+                      ) : null}
+                  </div>
+                )
+                }
+              />)
+            : (
+              <Fragment>
+                {trigger}
+                {content}
+                {showCloseBtn
+                  ? (
+                    <Button
+                      className={styles.close}
+                      label={intl.formatMessage(intlMessages.close)}
+                      size="lg"
+                      color="default"
+                      onClick={this.handleHide}
+                    />
+                  ) : null}
+              </Fragment>
+            )
+        }
       </div>
     );
   }
diff --git a/bigbluebutton-html5/imports/ui/components/dropdown/content/component.jsx b/bigbluebutton-html5/imports/ui/components/dropdown/content/component.jsx
index 9bcbe4fa6917dce3c5dd12abdf43401a9350446d..f6d38545c89e611f161e5524a148ff505aaf6777 100644
--- a/bigbluebutton-html5/imports/ui/components/dropdown/content/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/dropdown/content/component.jsx
@@ -26,8 +26,14 @@ const defaultProps = {
 export default class DropdownContent extends Component {
   render() {
     const {
-      placement, children, className,
-      dropdownToggle, dropdownShow, dropdownHide, dropdownIsOpen,
+      placement,
+      children,
+      className,
+      dropdownToggle,
+      dropdownShow,
+      dropdownHide,
+      dropdownIsOpen,
+      keepOpen,
       ...restProps
     } = this.props;
 
@@ -38,6 +44,7 @@ export default class DropdownContent extends Component {
       dropdownToggle,
       dropdownShow,
       dropdownHide,
+      keepOpen,
     }));
 
     return (
diff --git a/bigbluebutton-html5/imports/ui/components/dropdown/list/component.jsx b/bigbluebutton-html5/imports/ui/components/dropdown/list/component.jsx
index abd09fe45840c6cd4ca50029ab3210699a104481..03310297f2e4846b32ca71bf3c692bbb57e6640b 100755
--- a/bigbluebutton-html5/imports/ui/components/dropdown/list/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/dropdown/list/component.jsx
@@ -45,8 +45,8 @@ export default class DropdownList extends Component {
   }
 
   componentDidUpdate() {
-    const { focusedIndex } = this.state;
 
+    const { focusedIndex } = this.state;
     const children = [].slice.call(this._menu.children);
     this.menuRefs = children.filter(child => child.getAttribute('role') === 'menuitem');
 
@@ -126,13 +126,14 @@ export default class DropdownList extends Component {
   }
 
   handleItemClick(event, callback) {
-    const { getDropdownMenuParent, onActionsHide, dropdownHide } = this.props;
-
-    if (getDropdownMenuParent) {
-      onActionsHide();
-    } else {
-      this.setState({ focusedIndex: null });
-      dropdownHide();
+    const { getDropdownMenuParent, onActionsHide, dropdownHide, keepOpen} = this.props;
+    if(!keepOpen) {
+      if (getDropdownMenuParent) {
+        onActionsHide();
+      } else {
+        this.setState({ focusedIndex: null });
+        dropdownHide();
+      }
     }
 
     if (typeof callback === 'function') {
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/service.js b/bigbluebutton-html5/imports/ui/components/user-list/service.js
index 1cc441d9a0257654f8f672a5ee7d1a66148ca3ff..4ca35b290a7a7f2b92b5de0fd71765570cf23ee2 100755
--- a/bigbluebutton-html5/imports/ui/components/user-list/service.js
+++ b/bigbluebutton-html5/imports/ui/components/user-list/service.js
@@ -435,14 +435,30 @@ const muteAllExceptPresenter = (userId) => { makeCall('muteAllExceptPresenter',
 
 const changeRole = (userId, role) => { makeCall('changeRole', userId, role); };
 
-const roving = (event, changeState, elementsList, element) => {
+const focusFirstDropDownItem = () => {
+  const dropdownContent = document.querySelector('div[data-test="dropdownContent"][style="visibility: visible;"]');
+  if (!dropdownContent) return;
+  const list = dropdownContent.getElementsByTagName('li');
+  list[0].focus();
+};
+
+const roving = (...args) => {
+  const [
+    event,
+    changeState,
+    elementsList,
+    element,
+  ] = args;
+
   this.selectedElement = element;
+  const numberOfChilds = elementsList.childElementCount;
   const menuOpen = Session.get('dropdownOpen') || false;
 
   if (menuOpen) {
     const menuChildren = document.activeElement.getElementsByTagName('li');
 
     if ([KEY_CODES.ESCAPE, KEY_CODES.ARROW_LEFT].includes(event.keyCode)) {
+      Session.set('dropdownOpen', false);
       document.activeElement.click();
     }
 
@@ -463,13 +479,15 @@ const roving = (event, changeState, elementsList, element) => {
   }
 
   if ([KEY_CODES.ESCAPE, KEY_CODES.TAB].includes(event.keyCode)) {
+    Session.set('dropdownOpen', false);
     document.activeElement.blur();
     changeState(null);
   }
 
   if (event.keyCode === KEY_CODES.ARROW_DOWN) {
     const firstElement = elementsList.firstChild;
-    let elRef = element ? element.nextSibling : firstElement;
+    let elRef = element && numberOfChilds > 1 ? element.nextSibling : firstElement;
+
     elRef = elRef || firstElement;
     changeState(elRef);
   }
@@ -482,7 +500,10 @@ const roving = (event, changeState, elementsList, element) => {
   }
 
   if ([KEY_CODES.ARROW_RIGHT, KEY_CODES.SPACE, KEY_CODES.ENTER].includes(event.keyCode)) {
-    document.activeElement.firstChild.click();
+    const tether = document.activeElement.firstChild;
+    const dropdownTrigger = tether.firstChild;
+    dropdownTrigger.click();
+    focusFirstDropDownItem();
   }
 };
 
@@ -549,4 +570,5 @@ export default {
   hasPrivateChatBetweenUsers,
   toggleUserLock,
   requestUserInformation,
+  focusFirstDropDownItem,
 };
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/styles.scss b/bigbluebutton-html5/imports/ui/components/user-list/styles.scss
index 62212b02ce16ded93da2e349e56541c6e66eeaee..8c55231c2bfd222c87dce242b9c1a7e7d1147444 100755
--- a/bigbluebutton-html5/imports/ui/components/user-list/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/user-list/styles.scss
@@ -144,6 +144,7 @@
 .userListColumn {
   @extend %flex-column;
   min-height: 0;
+  flex-grow: 1;
 }
 
 .enter,
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/styles.scss b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/styles.scss
index 3c24009616b4d975c8b125842361d220a403a360..4b8d5621f4944e56f26efbb1d2d74ce2f3581fec 100755
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/styles.scss
@@ -37,6 +37,35 @@
   outline-color: transparent !important;
 }
 
+.virtulizedScrollableList {
+  @include elementFocus(var(--list-item-bg-hover));
+  @include scrollbox-vertical(var(--user-list-bg));
+  @include highContrastOutline();
+
+  &:focus-within,
+  &:focus {
+    outline-style: solid;
+  }
+
+  &:active {
+    box-shadow: none;
+    border-radius: none;
+  }
+
+  outline-width: 1px !important;
+  outline-color: transparent !important;
+
+  flex-grow: 1;
+  flex-shrink: 1;
+
+  margin: 0 0 1px var(--md-padding-y);
+
+  [dir="rtl"] & {
+    margin: 0 var(--md-padding-y) 1px 0;
+  }
+  margin-left: 0;
+}
+
 .list {
   margin: 0 0 1px var(--md-padding-y);
 
@@ -152,6 +181,11 @@
   flex-shrink: 1;
 }
 
+.scrollStyle {
+  @include scrollbox-vertical($bg-color: #f3f6f9);
+  
+}
+
 .noteLock {
   font-weight: 200;
   font-size: var(--font-size-smaller);
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx
index a897a092bda2746d5b0a4c19e95bc671393af150..e918f217c22bbec6da9b9ac1ecde8eeef76d6525 100755
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/component.jsx
@@ -1,11 +1,15 @@
 import React, { Component } from 'react';
-import { TransitionGroup, CSSTransition } from 'react-transition-group';
 import { defineMessages } from 'react-intl';
 import PropTypes from 'prop-types';
-import cx from 'classnames';
 import { styles } from '/imports/ui/components/user-list/user-list-content/styles';
 import _ from 'lodash';
 import { findDOMNode } from 'react-dom';
+import {
+  List,
+  AutoSizer,
+  CellMeasurer,
+  CellMeasurerCache,
+} from 'react-virtualized';
 import UserListItemContainer from './user-list-item/container';
 import UserOptionsContainer from './user-options/container';
 
@@ -47,8 +51,15 @@ class UserParticipants extends Component {
   constructor() {
     super();
 
+    this.cache = new CellMeasurerCache({
+      fixedWidth: true,
+      keyMapper: () => 1,
+    });
+
     this.state = {
       selectedUser: null,
+      isOpen: false,
+      scrollArea: false,
     };
 
     this.userRefs = [];
@@ -56,7 +67,7 @@ class UserParticipants extends Component {
     this.getScrollContainerRef = this.getScrollContainerRef.bind(this);
     this.rove = this.rove.bind(this);
     this.changeState = this.changeState.bind(this);
-    this.getUsers = this.getUsers.bind(this);
+    this.rowRenderer = this.rowRenderer.bind(this);
     this.handleClickSelectedUser = this.handleClickSelectedUser.bind(this);
   }
 
@@ -82,13 +93,20 @@ class UserParticipants extends Component {
   }
 
   componentDidUpdate(prevProps, prevState) {
-    const { selectedUser } = this.state;
-
-    if (selectedUser === prevState.selectedUser) return;
+    const { compact } = this.props;
+    const { selectedUser,  scrollArea } = this.state;
+    if (!compact && (!prevState.scrollArea && scrollArea)) {
+      scrollArea.addEventListener(
+        'keydown',
+        this.rove,
+      );
+    }
 
     if (selectedUser) {
       const { firstChild } = selectedUser;
-      if (firstChild) firstChild.focus();
+      if (!firstChild.isEqualNode(document.activeElement)) {
+        firstChild.focus();
+      }
     }
   }
 
@@ -101,7 +119,12 @@ class UserParticipants extends Component {
     return this.refScrollContainer;
   }
 
-  getUsers() {
+  rowRenderer({
+    index,
+    parent,
+    style,
+    key,
+  }) {
     const {
       compact,
       setEmojiStatus,
@@ -110,21 +133,22 @@ class UserParticipants extends Component {
       currentUser,
       meetingIsBreakout,
     } = this.props;
+    const { scrollArea } = this.state;
+    const user = users[index];
 
-    let index = -1;
-
-    return users.map(u => (
-      <CSSTransition
-        classNames={listTransition}
-        appear
-        enter
-        exit
-        timeout={0}
-        component="div"
-        className={cx(styles.participantsList)}
-        key={u.userId}
+    return (
+      <CellMeasurer
+        key={key}
+        cache={this.cache}
+        columnIndex={0}
+        parent={parent}
+        rowIndex={index}
       >
-        <div ref={(node) => { this.userRefs[index += 1] = node; }}>
+        <span
+          style={style}
+          key={key}
+          id={`user-${user.userId}`}
+        >
           <UserListItemContainer
             {...{
               compact,
@@ -132,13 +156,14 @@ class UserParticipants extends Component {
               requestUserInformation,
               currentUser,
               meetingIsBreakout,
+              scrollArea,
             }}
-            user={u}
+            user={user}
             getScrollContainerRef={this.getScrollContainerRef}
           />
-        </div>
-      </CSSTransition>
-    ));
+        </span>
+      </CellMeasurer>
+    );
   }
 
   handleClickSelectedUser(event) {
@@ -151,8 +176,9 @@ class UserParticipants extends Component {
 
   rove(event) {
     const { roving } = this.props;
-    const { selectedUser } = this.state;
-    const usersItemsRef = findDOMNode(this.refScrollItems);
+    const { selectedUser, scrollArea } = this.state;
+    const usersItemsRef = findDOMNode(scrollArea.firstChild);
+
     roving(event, this.changeState, usersItemsRef, selectedUser);
   }
 
@@ -169,6 +195,7 @@ class UserParticipants extends Component {
       currentUser,
       meetingIsBreakout,
     } = this.props;
+    const { isOpen, scrollArea } = this.state;
 
     return (
       <div className={styles.userListColumn}>
@@ -198,15 +225,40 @@ class UserParticipants extends Component {
             : <hr className={styles.separator} />
         }
         <div
-          className={styles.scrollableList}
+          className={styles.virtulizedScrollableList}
           tabIndex={0}
-          ref={(ref) => { this.refScrollContainer = ref; }}
+          ref={(ref) => {
+            this.refScrollContainer = ref;
+          }}
         >
-          <div className={styles.list}>
-            <TransitionGroup ref={(ref) => { this.refScrollItems = ref; }}>
-              {this.getUsers()}
-            </TransitionGroup>
-          </div>
+          <span id="destination" />
+          <AutoSizer>
+            {({ height, width }) => (
+              <List
+                {...{
+                  isOpen,
+                  users,
+                }}
+                ref={(ref) => {
+                  if (ref !== null) {
+                    this.listRef = ref;
+                  }
+
+                  if (ref !== null && !scrollArea) {                    
+                    this.setState({ scrollArea: findDOMNode(ref) });
+                  }
+                }}
+                rowHeight={this.cache.rowHeight}
+                rowRenderer={this.rowRenderer}
+                rowCount={users.length}
+                height={height - 1}
+                width={width - 1}
+                className={styles.scrollStyle}
+                overscanRowCount={30}
+                deferredMeasurementCache={this.cache}
+              />
+            )}
+          </AutoSizer>
         </div>
       </div>
     );
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx
index daf9550083152d0bc2071c9cca34bbbebdbd1391..873843591058d07f18279bdb09232cea0d8d9834 100644
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx
@@ -45,6 +45,10 @@ class UserListItem extends PureComponent {
       isMeteorConnected,
       isMe,
       voiceUser,
+      scrollArea,
+      notify,
+      raiseHandAudioAlert,
+      raiseHandPushAlert,
     } = this.props;
 
     const contents = (
@@ -76,6 +80,10 @@ class UserListItem extends PureComponent {
           isMeteorConnected,
           isMe,
           voiceUser,
+          scrollArea,
+          notify,
+          raiseHandAudioAlert,
+          raiseHandPushAlert,
         }}
       />
     );
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx
index 3fbbcf92988b812f8bc015673183bb1638e83939..a784bdfcb5bdfcd28b0d67dc73ae700b6a7e38af 100755
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/component.jsx
@@ -4,12 +4,12 @@ import PropTypes from 'prop-types';
 import { findDOMNode } from 'react-dom';
 import UserAvatar from '/imports/ui/components/user-avatar/component';
 import Icon from '/imports/ui/components/icon/component';
-import Dropdown from '/imports/ui/components/dropdown/component';
 import DropdownTrigger from '/imports/ui/components/dropdown/trigger/component';
 import DropdownContent from '/imports/ui/components/dropdown/content/component';
 import DropdownList from '/imports/ui/components/dropdown/list/component';
 import DropdownListItem from '/imports/ui/components/dropdown/list/item/component';
 import DropdownListSeparator from '/imports/ui/components/dropdown/list/separator/component';
+import Dropdown from '/imports/ui/components/dropdown/component';
 import lockContextContainer from '/imports/ui/components/lock-viewers/context/container';
 import { withModalMounter } from '/imports/ui/components/modal/service';
 import RemoveUserModal from '/imports/ui/components/modal/remove-user/component';
@@ -18,6 +18,7 @@ import { Session } from 'meteor/session';
 import { styles } from './styles';
 import UserName from '../user-name/component';
 import UserIcons from '../user-icons/component';
+import Service from '../../../../service';
 
 const messages = defineMessages({
   presenter: {
@@ -305,7 +306,10 @@ class UserDropdown extends PureComponent {
           {
             showNestedOptions: true,
             isActionsOpen: true,
-          }, Session.set('dropdownOpen', true),
+          }, () => {
+            Session.set('dropdownOpen', true);
+            Service.focusFirstDropDownItem();
+          },
         ),
         'user',
         'right_arrow',
@@ -468,26 +472,24 @@ class UserDropdown extends PureComponent {
    * Check if the dropdown is visible, if so, check if should be draw on top or bottom direction.
    */
   checkDropdownDirection() {
-    const { getScrollContainerRef } = this.props;
+    const { scrollArea } = this.props;
     if (this.isDropdownActivedByUser()) {
       const dropdown = this.getDropdownMenuParent();
       const dropdownTrigger = dropdown.children[0];
-      const dropdownContent = dropdown.children[1];
-
-      const scrollContainer = getScrollContainerRef();
-
       const nextState = {
         dropdownVisible: true,
       };
+      const dropdownContent = findDOMNode(this.dropdownContent);
+      const dropdownBoundaries = dropdownContent.getBoundingClientRect();
 
       const isDropdownVisible = UserDropdown.checkIfDropdownIsVisible(
-        dropdownContent.offsetTop,
-        dropdownContent.offsetHeight,
+        dropdownBoundaries.y,
+        dropdownBoundaries.height,
       );
 
-      if (!isDropdownVisible) {
+      if (!isDropdownVisible && scrollArea) {
         const { offsetTop, offsetHeight } = dropdownTrigger;
-        const offsetPageTop = (offsetTop + offsetHeight) - scrollContainer.scrollTop;
+        const offsetPageTop = (offsetTop + offsetHeight) - scrollArea.scrollTop;
 
         nextState.dropdownOffset = window.innerHeight - offsetPageTop;
         nextState.dropdownDirection = 'bottom';
@@ -620,7 +622,7 @@ class UserDropdown extends PureComponent {
     );
 
     if (!actions.length) return contents;
-
+    const placement = `right ${dropdownDirection}`;
     return (
       <Dropdown
         ref={(ref) => { this.dropdown = ref; }}
@@ -632,6 +634,9 @@ class UserDropdown extends PureComponent {
         aria-haspopup="true"
         aria-live="assertive"
         aria-relevant="additions"
+        placement={placement}
+        getContent={dropdownContent => this.dropdownContent = dropdownContent}
+        tethered
       >
         <DropdownTrigger>
           {contents}
@@ -639,10 +644,9 @@ class UserDropdown extends PureComponent {
         <DropdownContent
           style={{
             visibility: dropdownVisible ? 'visible' : 'hidden',
-            [dropdownDirection]: `${dropdownOffset}px`,
           }}
           className={styles.dropdownContent}
-          placement={`right ${dropdownDirection}`}
+          placement={placement}
         >
           <DropdownList
             ref={(ref) => { this.list = ref; }}
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/styles.scss b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/styles.scss
index 50e88bcdfa77a95641a5acb9e67fe64191328638..fd507dd5b78247b7db29c695d11ca1e4b6c4b369 100755
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/styles.scss
@@ -133,6 +133,12 @@
   @extend %text-elipsis;
   cursor: default;
   min-width: 10vw;
+  @include mq($medium-only) {
+    min-width: 13vw;
+  }
+  @include mq($large-up) {
+    min-width: 8vw;
+  }
   max-width: 100%;
   overflow: visible;
 }
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/theteredDropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/theteredDropdown/component.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..8de17fb59e83252361b9c549d8a1b3d5934a2832
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/user-dropdown/theteredDropdown/component.jsx
@@ -0,0 +1,279 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { findDOMNode } from 'react-dom';
+import cx from 'classnames';
+import { isMobile } from 'react-device-detect';
+import { defineMessages, injectIntl, intlShape } from 'react-intl';
+import Button from '/imports/ui/components/button/component';
+import screenreaderTrap from 'makeup-screenreader-trap';
+import TetherComponent from 'react-tether';
+import { styles } from '/imports/ui/components/dropdown/styles';
+
+import DropdownTrigger from '/imports/ui/components/dropdown/trigger/component';
+import DropdownContent from '/imports/ui/components/dropdown/content/component';
+
+const intlMessages = defineMessages({
+  close: {
+    id: 'app.dropdown.close',
+    description: 'Close button label',
+  },
+});
+
+const noop = () => { };
+
+const propTypes = {
+  /**
+   * The dropdown needs a trigger and a content component as children
+   */
+  children: (props, propName, componentName) => {
+    const children = props[propName];
+
+    if (!children || children.length < 2) {
+      return new Error(`Invalid prop \`${propName}\` supplied to`
+        + ` \`${componentName}\`. Validation failed.`);
+    }
+
+    const trigger = children.find(x => x.type === DropdownTrigger);
+    const content = children.find(x => x.type === DropdownContent);
+
+    if (!trigger) {
+      return new Error(`Invalid prop \`${propName}\` supplied to`
+        + ` \`${componentName}\`. Missing \`DropdownTrigger\`. Validation failed.`);
+    }
+
+    if (!content) {
+      return new Error(`Invalid prop \`${propName}\` supplied to`
+        + ` \`${componentName}\`. Missing \`DropdownContent\`. Validation failed.`);
+    }
+
+    return null;
+  },
+  isOpen: PropTypes.bool,
+  keepOpen: PropTypes.bool,
+  onHide: PropTypes.func,
+  onShow: PropTypes.func,
+  autoFocus: PropTypes.bool,
+  intl: intlShape.isRequired,
+};
+
+const defaultProps = {
+  children: null,
+  onShow: noop,
+  onHide: noop,
+  autoFocus: false,
+  isOpen: false,
+  keepOpen: null,
+};
+
+const attachments = {
+  'right-bottom': 'bottom left',
+  'right-top': 'bottom left',
+};
+
+const targetAttachments = {
+  'right-bottom': 'bottom right',
+  'right-top': 'top right',
+};
+
+class Dropdown extends Component {
+  constructor(props) {
+    super(props);
+    this.state = { isOpen: false };
+    this.handleShow = this.handleShow.bind(this);
+    this.handleHide = this.handleHide.bind(this);
+    this.handleToggle = this.handleToggle.bind(this);
+    this.handleWindowClick = this.handleWindowClick.bind(this);
+  }
+
+  componentWillUpdate(nextProps, nextState) {
+    return nextState.isOpen ? screenreaderTrap.trap(this.dropdown) : screenreaderTrap.untrap();
+  }
+
+  componentDidUpdate(prevProps, prevState) {
+    const {
+      onShow,
+      onHide,
+      keepOpen,
+    } = this.props;
+    const { isOpen } = this.state;
+
+    if (isOpen && !prevState.isOpen) { onShow(); }
+
+    if (!isOpen && prevState.isOpen) { onHide(); }
+
+    if (prevProps.keepOpen && !keepOpen) { onHide(); }
+  }
+
+  handleShow() {
+    Session.set('dropdownOpen', true);
+    const {
+      onShow,
+    } = this.props;
+    this.setState({ isOpen: true }, () => {
+      const { addEventListener } = window;
+      onShow();
+      addEventListener('click', this.handleWindowClick, true);
+    });
+  }
+
+  handleHide() {
+    Session.set('dropdownOpen', false);
+    const { onHide } = this.props;
+    this.setState({ isOpen: false }, () => {
+      const { removeEventListener } = window;
+      onHide();
+      removeEventListener('click', this.handleWindowClick, true);
+    });
+  }
+
+  handleWindowClick(event) {
+    const { keepOpen, onHide } = this.props;
+    const { isOpen } = this.state;
+    const triggerElement = findDOMNode(this.trigger);
+    const contentElement = findDOMNode(this.content);
+    if (!(triggerElement && contentElement)) return;
+    if (triggerElement && triggerElement.contains(event.target)) {
+      if (keepOpen) {
+        onHide();
+        return;
+      }
+      if (isOpen) {
+        this.handleHide();
+        return;
+      }
+    }
+
+    if (keepOpen && isOpen && !contentElement.contains(event.target)) {
+      if (triggerElement) {
+        const { parentElement } = triggerElement;
+        if (parentElement) parentElement.focus();
+      }
+      onHide();
+      this.handleHide();
+      return;
+    }
+
+    if (keepOpen && triggerElement) {
+      const { parentElement } = triggerElement;
+      if (parentElement) parentElement.focus();
+    }
+
+    if (keepOpen !== null) return;
+    this.handleHide();
+  }
+
+  handleToggle() {
+    const { isOpen } = this.state;
+    return isOpen ? this.handleHide() : this.handleShow();
+  }
+
+  render() {
+    const {
+      children,
+      className,
+      intl,
+      keepOpen,
+      getContent,
+      placement,
+      ...otherProps
+    } = this.props;
+
+    const { isOpen } = this.state;
+
+    let trigger = children.find(x => x.type === DropdownTrigger);
+    let content = children.find(x => x.type === DropdownContent);
+
+    trigger = React.cloneElement(trigger, {
+      ref: (ref) => { this.trigger = ref; },
+      dropdownIsOpen: isOpen,
+      dropdownToggle: this.handleToggle,
+      dropdownShow: this.handleShow,
+      dropdownHide: this.handleHide,
+    });
+
+    content = React.cloneElement(content, {
+      ref: (ref) => {
+        getContent(ref);
+        this.content = ref;
+      },
+      keepOpen,
+      'aria-expanded': isOpen,
+      dropdownIsOpen: isOpen,
+      dropdownToggle: this.handleToggle,
+      dropdownShow: this.handleShow,
+      dropdownHide: this.handleHide,
+    });
+
+    const showCloseBtn = (isOpen && keepOpen) || (isOpen && keepOpen === null);
+    const placements = placement.replace(' ', '-');
+    // workaround
+    const test = isMobile ? {
+      width: '100%',
+      height: '100%',
+      transform: 'translateY(0)',
+    } : {
+      width: '',
+      height: '',
+      transform: '',
+    };
+    return (
+      <div
+        className={cx(styles.dropdown, className)}
+        aria-live={otherProps['aria-live']}
+        aria-relevant={otherProps['aria-relevant']}
+        aria-haspopup={otherProps['aria-haspopup']}
+        aria-label={otherProps['aria-label']}
+        ref={(node) => { this.dropdown = node; }}
+        tabIndex={-1}
+      >
+        <TetherComponent
+          style={{
+            zIndex: isOpen ? 15 : '',
+            ...test,
+          }}
+          attachment={
+            isMobile ? 'middle bottom'
+              : attachments[placements]
+          }
+          targetAttachment={
+            isMobile ? ''
+              : targetAttachments[placements]
+          }
+
+          constraints={[
+            {
+              to: 'scrollParent',
+            },
+          ]}
+
+          renderTarget={ref => (
+            <span ref={ref}>
+              {trigger}
+            </span>)}
+          renderElement={ref => (
+            <div
+              ref={ref}
+            >
+              {content}
+              {showCloseBtn
+                ? (
+                  <Button
+                    className={styles.close}
+                    label={intl.formatMessage(intlMessages.close)}
+                    size="lg"
+                    color="default"
+                    onClick={this.handleHide}
+                  />
+                ) : null}
+            </div>
+          )
+          }
+        />
+      </div>
+    );
+  }
+}
+
+Dropdown.propTypes = propTypes;
+Dropdown.defaultProps = defaultProps;
+export default injectIntl(Dropdown);
diff --git a/bigbluebutton-html5/package-lock.json b/bigbluebutton-html5/package-lock.json
index 39bf129f95a84c3c2ed33753a5b23f55f553b8d5..b6c8d5710a859de6aa52fe12680e402b70886dcf 100644
--- a/bigbluebutton-html5/package-lock.json
+++ b/bigbluebutton-html5/package-lock.json
@@ -8899,6 +8899,15 @@
         "prop-types": "^15.5.0"
       }
     },
+    "react-tether": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/react-tether/-/react-tether-2.0.7.tgz",
+      "integrity": "sha512-OZAMoT0y1//SN357HiJKic+Ax/kMe3CwdaDT+05P/DHMR9adTYH2RTMDZMjw/OGMmLlBFg6UrDFXiulVKKIBRw==",
+      "requires": {
+        "prop-types": "^15.6.2",
+        "tether": "^1.4.5"
+      }
+    },
     "react-toastify": {
       "version": "4.5.2",
       "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-4.5.2.tgz",
@@ -10291,6 +10300,11 @@
         "minimatch": "^3.0.4"
       }
     },
+    "tether": {
+      "version": "1.4.7",
+      "resolved": "https://registry.npmjs.org/tether/-/tether-1.4.7.tgz",
+      "integrity": "sha512-Z0J1aExjoFU8pybVkQAo/vD2wfSO63r+XOPfWQMC5qtf1bI7IWqNk4MiyBcgvvnY8kqnY06dVdvwTK2S3PU/Fw=="
+    },
     "text-hex": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
diff --git a/bigbluebutton-html5/package.json b/bigbluebutton-html5/package.json
index b6a0e4e4a552d0b3f0598410d5f07c6351c99c2a..2ecdc381b26fefd25d67fed4c71ac63e5d233825 100755
--- a/bigbluebutton-html5/package.json
+++ b/bigbluebutton-html5/package.json
@@ -67,6 +67,7 @@
     "react-player": "^2.5.0",
     "react-render-in-browser": "^1.1.1",
     "react-tabs": "^2.3.1",
+    "react-tether": "^2.0.7",
     "react-toastify": "^4.5.2",
     "react-toggle": "~4.0.2",
     "react-transition-group": "^2.9.0",