diff --git a/res/css/structures/_LeftPanel2.scss b/res/css/structures/_LeftPanel2.scss index 837a1d1f0d..98f23a058b 100644 --- a/res/css/structures/_LeftPanel2.scss +++ b/res/css/structures/_LeftPanel2.scss @@ -132,16 +132,6 @@ $tagPanelWidth: 70px; // only applies in this file, used for calculations .mx_LeftPanel2_roomListContainer { width: 68px; - .mx_LeftPanel2_userHeader { - .mx_LeftPanel2_headerRow { - justify-content: center; - } - - .mx_LeftPanel2_userAvatarContainer { - margin-right: 0; - } - } - .mx_LeftPanel2_filterContainer { // Organize the flexbox into a centered column layout flex-direction: column; diff --git a/res/css/structures/_UserMenu.scss b/res/css/structures/_UserMenu.scss index a15eeb6c81..bbb1e1cc7b 100644 --- a/res/css/structures/_UserMenu.scss +++ b/res/css/structures/_UserMenu.scss @@ -15,39 +15,7 @@ limitations under the License. */ .mx_UserMenu { - // Create a row-based flexbox to ensure items stay aligned correctly. - display: flex; - align-items: center; - - .mx_UserMenu_userAvatarContainer { - position: relative; // to make default avatars work - margin-right: 8px; - height: 32px; // to remove the unknown 4px gap the browser puts below it - - .mx_UserMenu_userAvatar { - border-radius: 32px; // should match avatar size - } - } - - .mx_UserMenu_userName { - font-weight: 600; - font-size: $font-15px; - line-height: $font-20px; - flex: 1; - - // Ellipsize any text overflow - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - } - .mx_UserMenu_headerButtons { - // No special styles: the rest of the layout happens to make it work. - } -} - -.mx_UserMenuButton { - > span { width: 16px; height: 16px; position: relative; @@ -67,6 +35,50 @@ limitations under the License. mask-image: url('$(res)/img/feather-customised/more-horizontal.svg'); } } + + .mx_UserMenu_row { + // Create a row-based flexbox to ensure items stay aligned correctly. + display: flex; + align-items: center; + + .mx_UserMenu_userAvatarContainer { + position: relative; // to make default avatars work + margin-right: 8px; + height: 32px; // to remove the unknown 4px gap the browser puts below it + + .mx_UserMenu_userAvatar { + border-radius: 32px; // should match avatar size + } + } + + .mx_UserMenu_userName { + font-weight: 600; + font-size: $font-15px; + line-height: $font-20px; + flex: 1; + + // Ellipsize any text overflow + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + + .mx_UserMenu_headerButtons { + // No special styles: the rest of the layout happens to make it work. + } + } + + &.mx_UserMenu_minimized { + .mx_UserMenu_userHeader { + .mx_UserMenu_row { + justify-content: center; + } + + .mx_UserMenu_userAvatarContainer { + margin-right: 0; + } + } + } } .mx_UserMenu_contextMenu { diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index 89593aa702..6e3670447e 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -36,6 +36,7 @@ import {getHomePageUrl} from "../../utils/pages"; import { OwnProfileStore } from "../../stores/OwnProfileStore"; import { UPDATE_EVENT } from "../../stores/AsyncStore"; import BaseAvatar from '../views/avatars/BaseAvatar'; +import classNames from "classnames"; interface IProps { isMinimized: boolean; @@ -108,7 +109,9 @@ export default class UserMenu extends React.Component { this.setState({menuDisplayed: true}); }; - private onCloseMenu = () => { + private onCloseMenu = (ev: InputEvent) => { + ev.preventDefault(); + ev.stopPropagation(); this.setState({menuDisplayed: false}); }; @@ -160,147 +163,132 @@ export default class UserMenu extends React.Component { defaultDispatcher.dispatch({action: 'view_home_page'}); }; - private renderMenuButton(): React.ReactNode { - let contextMenu; - if (this.state.menuDisplayed) { - let hostingLink; - const signupLink = getHostingLink("user-context-menu"); - if (signupLink) { - hostingLink = ( -
- {_t( - "Upgrade to your own domain", {}, - { - a: sub => ( - {sub} - ), - }, - )} -
- ); - } + private renderContextMenu = (): React.ReactNode => { + if (!this.state.menuDisplayed) return null; - let homeButton = null; - if (this.hasHomePage) { - homeButton = ( -
  • - - - {_t("Home")} - -
  • - ); - } - - const elementRect = this.buttonRef.current.getBoundingClientRect(); - contextMenu = ( - -
    -
    -
    - - {OwnProfileStore.instance.displayName} - - - {MatrixClientPeg.get().getUserId()} - -
    -
    - {_t("Switch -
    -
    - {hostingLink} -
    -
      - {homeButton} -
    • - this.onSettingsOpen(e, USER_NOTIFICATIONS_TAB)}> - - {_t("Notification settings")} - -
    • -
    • - this.onSettingsOpen(e, USER_SECURITY_TAB)}> - - {_t("Security & privacy")} - -
    • -
    • - this.onSettingsOpen(e, null)}> - - {_t("All settings")} - -
    • -
    • - - - {_t("Archived rooms")} - -
    • -
    • - - - {_t("Feedback")} - -
    • -
    -
    -
    -
      -
    • - - - {_t("Sign out")} - -
    • -
    -
    -
    -
    + let hostingLink; + const signupLink = getHostingLink("user-context-menu"); + if (signupLink) { + hostingLink = ( +
    + {_t( + "Upgrade to your own domain", {}, + { + a: sub => ( + {sub} + ), + }, + )} +
    ); } + let homeButton = null; + if (this.hasHomePage) { + homeButton = ( +
  • + + + {_t("Home")} + +
  • + ); + } + + const elementRect = this.buttonRef.current.getBoundingClientRect(); return ( - - - {/* masked image in CSS */} - - {contextMenu} - + +
    +
    +
    + + {OwnProfileStore.instance.displayName} + + + {MatrixClientPeg.get().getUserId()} + +
    +
    + {_t("Switch +
    +
    + {hostingLink} +
    +
      + {homeButton} +
    • + this.onSettingsOpen(e, USER_NOTIFICATIONS_TAB)}> + + {_t("Notification settings")} + +
    • +
    • + this.onSettingsOpen(e, USER_SECURITY_TAB)}> + + {_t("Security & privacy")} + +
    • +
    • + this.onSettingsOpen(e, null)}> + + {_t("All settings")} + +
    • +
    • + + + {_t("Archived rooms")} + +
    • +
    • + + + {_t("Feedback")} + +
    • +
    +
    +
    +
      +
    • + + + {_t("Sign out")} + +
    • +
    +
    +
    +
    ); - } + }; public render() { + console.log(this.state); const avatarSize = 32; // should match border-radius of the avatar let name = {OwnProfileStore.instance.displayName}; let buttons = ( - {this.renderMenuButton()} + {/* masked image in CSS */} ); if (this.props.isMinimized) { @@ -308,22 +296,39 @@ export default class UserMenu extends React.Component { buttons = null; } + const classes = classNames({ + 'mx_UserMenu': true, + 'mx_UserMenu_minimized': this.props.isMinimized, + }); + return ( -
    - - - - {name} - {buttons} -
    + + +
    + + + + {name} + {buttons} +
    + {this.renderContextMenu()} +
    +
    + ); } }