diff --git a/res/css/_components.scss b/res/css/_components.scss index 006bac09c97..daa70166234 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -27,6 +27,9 @@ @import "./structures/_RoomView.scss"; @import "./structures/_ScrollPanel.scss"; @import "./structures/_SearchBox.scss"; +@import "./structures/_SpacePanel.scss"; +@import "./structures/_SpaceRoomDirectory.scss"; +@import "./structures/_SpaceRoomView.scss"; @import "./structures/_TabbedView.scss"; @import "./structures/_ToastContainer.scss"; @import "./structures/_UploadBar.scss"; @@ -56,6 +59,7 @@ @import "./views/context_menus/_MessageContextMenu.scss"; @import "./views/context_menus/_StatusMessageContextMenu.scss"; @import "./views/context_menus/_TagTileContextMenu.scss"; +@import "./views/dialogs/_AddExistingToSpaceDialog.scss"; @import "./views/dialogs/_AddressPickerDialog.scss"; @import "./views/dialogs/_Analytics.scss"; @import "./views/dialogs/_BugReportDialog.scss"; @@ -89,6 +93,7 @@ @import "./views/dialogs/_SettingsDialog.scss"; @import "./views/dialogs/_ShareDialog.scss"; @import "./views/dialogs/_SlashCommandHelpDialog.scss"; +@import "./views/dialogs/_SpaceSettingsDialog.scss"; @import "./views/dialogs/_TabbedIntegrationManagerDialog.scss"; @import "./views/dialogs/_TermsDialog.scss"; @import "./views/dialogs/_UploadConfirmDialog.scss"; @@ -232,6 +237,9 @@ @import "./views/settings/tabs/user/_PreferencesUserSettingsTab.scss"; @import "./views/settings/tabs/user/_SecurityUserSettingsTab.scss"; @import "./views/settings/tabs/user/_VoiceUserSettingsTab.scss"; +@import "./views/spaces/_SpaceBasicSettings.scss"; +@import "./views/spaces/_SpaceCreateMenu.scss"; +@import "./views/spaces/_SpacePublicShare.scss"; @import "./views/terms/_InlineTermsAgreement.scss"; @import "./views/toasts/_AnalyticsToast.scss"; @import "./views/toasts/_NonUrgentEchoFailureToast.scss"; diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index 168590502da..f1f27014eee 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -15,6 +15,7 @@ limitations under the License. */ $groupFilterPanelWidth: 56px; // only applies in this file, used for calculations +$roomListCollapsedWidth: 68px; .mx_LeftPanel { background-color: $roomlist-bg-color; @@ -37,18 +38,12 @@ $groupFilterPanelWidth: 56px; // only applies in this file, used for calculation // GroupFilterPanel handles its own CSS } - &:not(.mx_LeftPanel_hasGroupFilterPanel) { - .mx_LeftPanel_roomListContainer { - width: 100%; - } - } - // Note: The 'room list' in this context is actually everything that isn't the tag // panel, such as the menu options, breadcrumbs, filtering, etc .mx_LeftPanel_roomListContainer { - width: calc(100% - $groupFilterPanelWidth); background-color: $roomlist-bg-color; - + flex: 1 0 0; + min-width: 0; // Create another flexbox (this time a column) for the room list components display: flex; flex-direction: column; @@ -168,17 +163,10 @@ $groupFilterPanelWidth: 56px; // only applies in this file, used for calculation // These styles override the defaults for the minimized (66px) layout &.mx_LeftPanel_minimized { min-width: unset; - - // We have to forcefully set the width to override the resizer's style attribute. - &.mx_LeftPanel_hasGroupFilterPanel { - width: calc(68px + $groupFilterPanelWidth) !important; - } - &:not(.mx_LeftPanel_hasGroupFilterPanel) { - width: 68px !important; - } + width: unset !important; .mx_LeftPanel_roomListContainer { - width: 68px; + width: $roomListCollapsedWidth; .mx_LeftPanel_userHeader { flex-direction: row; diff --git a/res/css/structures/_RightPanel.scss b/res/css/structures/_RightPanel.scss index 5bf0d953f3b..5515fe40600 100644 --- a/res/css/structures/_RightPanel.scss +++ b/res/css/structures/_RightPanel.scss @@ -160,3 +160,20 @@ limitations under the License. mask-position: center; } } + +.mx_RightPanel_scopeHeader { + margin: 24px; + text-align: center; + font-weight: $font-semi-bold; + font-size: $font-18px; + line-height: $font-22px; + + .mx_BaseAvatar { + margin-right: 8px; + vertical-align: middle; + } + + .mx_BaseAvatar_image { + border-radius: 8px; + } +} diff --git a/res/css/structures/_SpacePanel.scss b/res/css/structures/_SpacePanel.scss new file mode 100644 index 00000000000..f98d441b4d7 --- /dev/null +++ b/res/css/structures/_SpacePanel.scss @@ -0,0 +1,321 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +$topLevelHeight: 32px; +$nestedHeight: 24px; +$gutterSize: 21px; +$activeStripeSize: 4px; + +.mx_SpacePanel { + flex: 0 0 auto; + background-color: $groupFilterPanel-bg-color; + padding: 0; + margin: 0; + + // Create another flexbox so the Panel fills the container + display: flex; + flex-direction: column; + overflow-y: auto; + + .mx_SpacePanel_spaceTreeWrapper { + flex: 1; + } + + .mx_SpacePanel_toggleCollapse { + flex: 0 0 auto; + width: 40px; + height: 40px; + mask-position: center; + mask-size: 32px; + mask-repeat: no-repeat; + margin-left: $gutterSize; + margin-bottom: 12px; + background-color: $roomlist-header-color; + mask-image: url('$(res)/img/element-icons/expand-space-panel.svg'); + + &.expanded { + transform: scaleX(-1); + } + } + + ul { + margin: 0; + list-style: none; + padding: 0; + padding-left: 16px; + } + + .mx_AutoHideScrollbar { + padding: 16px 12px 16px 0; + } + + .mx_SpaceButton_toggleCollapse { + cursor: pointer; + } + + .mx_SpaceItem { + position: relative; + } + + .mx_SpaceItem.collapsed { + & > .mx_SpaceButton > .mx_SpaceButton_toggleCollapse { + transform: rotate(-90deg); + } + + & > .mx_SpaceTreeLevel { + display: none; + } + } + + .mx_SpaceItem:not(.hasSubSpaces) > .mx_SpaceButton { + margin-left: $gutterSize; + + &.mx_SpaceButton_active { + &::before { + left: -$gutterSize; + } + } + } + + .mx_SpaceButton { + border-radius: 8px; + position: relative; + margin-bottom: 16px; + display: flex; + align-items: center; + + .mx_SpaceButton_name { + flex: 1; + margin-left: 8px; + white-space: nowrap; + display: block; + max-width: 150px; + text-overflow: ellipsis; + overflow: hidden; + + font-size: $font-14px; + line-height: $font-18px; + } + + .mx_SpaceButton_toggleCollapse { + width: calc($gutterSize - $activeStripeSize); + margin-left: 1px; + height: 20px; + mask-position: center; + mask-size: 20px; + mask-repeat: no-repeat; + background-color: $roomlist-header-color; + mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); + } + + &.mx_SpaceButton_active { + &::before { + position: absolute; + content: ''; + width: $activeStripeSize; + top: 0; + left: 0; + bottom: 0; + background-color: $accent-color; + border-radius: 0 4px 4px 0; + } + } + + .mx_SpaceButton_avatarPlaceholder { + width: $topLevelHeight; + min-width: $topLevelHeight; + height: $topLevelHeight; + border-radius: 8px; + + &::before { + position: absolute; + content: ''; + width: $topLevelHeight; + height: $topLevelHeight; + top: 0; + left: 0; + mask-position: center; + mask-repeat: no-repeat; + mask-size: 18px; + } + } + + &.mx_SpaceButton_home .mx_SpaceButton_avatarPlaceholder { + background-color: #ffffff; + + &::before { + background-color: #3f3d3d; + mask-image: url('$(res)/img/element-icons/home.svg'); + } + } + + &.mx_SpaceButton_new .mx_SpaceButton_avatarPlaceholder { + background-color: $accent-color; + transition: all .1s ease-in-out; // TODO transition + + &::before { + background-color: #ffffff; + mask-image: url('$(res)/img/element-icons/plus.svg'); + transition: all .2s ease-in-out; // TODO transition + } + } + + &.mx_SpaceButton_newCancel .mx_SpaceButton_avatarPlaceholder { + background-color: $icon-button-color; + + &::before { + transform: rotate(45deg); + } + } + + .mx_BaseAvatar_image { + border-radius: 8px; + } + + .mx_SpaceButton_menuButton { + width: 20px; + min-width: 20px; // yay flex + height: 20px; + margin-top: auto; + margin-bottom: auto; + position: relative; + display: none; + + &::before { + top: 2px; + left: 2px; + content: ''; + width: 16px; + height: 16px; + position: absolute; + mask-position: center; + mask-size: contain; + mask-repeat: no-repeat; + mask-image: url('$(res)/img/element-icons/context-menu.svg'); + background: $primary-fg-color; + } + } + } + + .mx_SpacePanel_badgeContainer { + height: 16px; + // don't set width so that it takes no space when there is no badge to show + margin: auto 0; // vertically align + + // Create a flexbox to make aligning dot badges easier + display: flex; + align-items: center; + + .mx_NotificationBadge { + margin: 0 2px; // centering + } + + .mx_NotificationBadge_dot { + // make the smaller dot occupy the same width for centering + margin-left: 7px; + margin-right: 7px; + } + } + + &.collapsed { + .mx_SpaceButton { + .mx_SpacePanel_badgeContainer { + position: absolute; + right: -8px; + top: -4px; + } + } + } + + &:not(.collapsed) { + .mx_SpaceButton:hover, + .mx_SpaceButton:focus-within, + .mx_SpaceButton_hasMenuOpen { + // Hide the badge container on hover because it'll be a menu button + .mx_SpacePanel_badgeContainer { + width: 0; + height: 0; + display: none; + } + + .mx_SpaceButton_menuButton { + display: block; + } + } + } + + /* root space buttons are bigger and not indented */ + & > .mx_AutoHideScrollbar { + & > .mx_SpaceButton { + height: $topLevelHeight; + + &.mx_SpaceButton_active::before { + height: $topLevelHeight; + } + } + + & > ul { + padding-left: 0; + } + } +} + +.mx_SpacePanel_contextMenu { + .mx_SpacePanel_contextMenu_header { + margin: 12px 16px 12px; + font-weight: $font-semi-bold; + font-size: $font-15px; + line-height: $font-18px; + } + + .mx_IconizedContextMenu_optionList .mx_AccessibleButton.mx_SpacePanel_contextMenu_inviteButton { + color: $accent-color; + + .mx_SpacePanel_iconInvite::before { + background-color: $accent-color; + mask-image: url('$(res)/img/element-icons/room/invite.svg'); + } + } + + .mx_SpacePanel_iconSettings::before { + mask-image: url('$(res)/img/element-icons/settings.svg'); + } + + .mx_SpacePanel_iconLeave::before { + mask-image: url('$(res)/img/element-icons/leave.svg'); + } + + .mx_SpacePanel_iconHome::before { + mask-image: url('$(res)/img/element-icons/roomlist/home.svg'); + } + + .mx_SpacePanel_iconMembers::before { + mask-image: url('$(res)/img/element-icons/room/members.svg'); + } + + .mx_SpacePanel_iconPlus::before { + mask-image: url('$(res)/img/element-icons/plus.svg'); + } + + .mx_SpacePanel_iconExplore::before { + mask-image: url('$(res)/img/element-icons/roomlist/explore.svg'); + } +} + + +.mx_SpacePanel_sharePublicSpace { + margin: 0; +} diff --git a/res/css/structures/_SpaceRoomDirectory.scss b/res/css/structures/_SpaceRoomDirectory.scss new file mode 100644 index 00000000000..7b942d358f3 --- /dev/null +++ b/res/css/structures/_SpaceRoomDirectory.scss @@ -0,0 +1,232 @@ +/* +Copyright 2015, 2016 OpenMarket Ltd +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_SpaceRoomDirectory_dialogWrapper > .mx_Dialog { + max-width: 960px; + height: 100%; +} + +.mx_SpaceRoomDirectory { + height: 100%; + margin-bottom: 12px; + color: $primary-fg-color; + word-break: break-word; + display: flex; + flex-direction: column; + + .mx_Dialog_title { + display: flex; + + .mx_BaseAvatar { + margin-right: 16px; + } + + .mx_BaseAvatar_image { + border-radius: 8px; + } + + > div { + > h1 { + font-weight: $font-semi-bold; + font-size: $font-18px; + line-height: $font-22px; + margin: 0; + } + + > div { + color: $secondary-fg-color; + font-size: $font-15px; + line-height: $font-24px; + } + } + } + + .mx_Dialog_content { + // TODO fix scrollbar + //display: flex; + //flex-direction: column; + //height: calc(100% - 80px); + + .mx_AccessibleButton_kind_link { + padding: 0; + } + + .mx_SearchBox { + margin: 24px 0 28px; + } + + .mx_SpaceRoomDirectory_listHeader { + display: flex; + font-size: $font-12px; + line-height: $font-15px; + color: $secondary-fg-color; + + .mx_FormButton { + margin-bottom: 8px; + } + + > span { + margin: auto 0 0 auto; + } + } + } +} + +.mx_SpaceRoomDirectory_list { + margin-top: 8px; + + .mx_SpaceRoomDirectory_roomCount { + > h3 { + display: inline; + font-weight: $font-semi-bold; + font-size: $font-18px; + line-height: $font-22px; + color: $primary-fg-color; + } + + > span { + margin-left: 8px; + font-size: $font-15px; + line-height: $font-24px; + color: $secondary-fg-color; + } + } + + .mx_SpaceRoomDirectory_subspace { + margin-top: 8px; + + .mx_SpaceRoomDirectory_subspace_info { + display: flex; + flex-direction: row; + align-items: center; + margin-bottom: 8px; + color: $secondary-fg-color; + font-weight: $font-semi-bold; + font-size: $font-12px; + line-height: $font-15px; + + .mx_BaseAvatar { + margin-right: 12px; + vertical-align: middle; + } + + .mx_BaseAvatar_image { + border-radius: 8px; + } + + .mx_SpaceRoomDirectory_actions { + text-align: right; + height: min-content; + margin-left: auto; + margin-right: 16px; + } + } + + .mx_SpaceRoomDirectory_subspace_children { + margin-left: 12px; + border-left: 2px solid $space-button-outline-color; + padding-left: 24px; + } + } + + .mx_SpaceRoomDirectory_roomTile { + padding: 16px; + border-radius: 8px; + border: 1px solid $space-button-outline-color; + margin: 8px 0 16px; + display: flex; + min-height: 76px; + box-sizing: border-box; + + &.mx_AccessibleButton:hover { + background-color: rgba(141, 151, 165, 0.1); + } + + .mx_BaseAvatar { + margin-right: 16px; + margin-top: 6px; + } + + .mx_SpaceRoomDirectory_roomTile_info { + display: inline-block; + font-size: $font-15px; + flex-grow: 1; + height: min-content; + margin: auto 0; + + .mx_SpaceRoomDirectory_roomTile_name { + font-weight: $font-semi-bold; + line-height: $font-18px; + } + .mx_SpaceRoomDirectory_roomTile_topic { + line-height: $font-24px; + color: $secondary-fg-color; + } + } + + .mx_SpaceRoomDirectory_roomTile_memberCount { + position: relative; + margin: auto 0 auto 24px; + padding: 0 0 0 28px; + line-height: $font-24px; + display: inline-block; + width: 32px; + + &::before { + position: absolute; + content: ''; + width: 24px; + height: 24px; + top: 0; + left: 0; + mask-position: center; + mask-repeat: no-repeat; + mask-size: contain; + background-color: $secondary-fg-color; + mask-image: url('$(res)/img/element-icons/community-members.svg'); + } + } + + .mx_SpaceRoomDirectory_actions { + width: 180px; + text-align: right; + height: min-content; + margin: auto 0 auto 28px; + + .mx_AccessibleButton { + vertical-align: middle; + + & + .mx_AccessibleButton { + margin-left: 24px; + } + } + } + } + + .mx_SpaceRoomDirectory_actions { + .mx_SpaceRoomDirectory_actionsText { + font-weight: normal; + font-size: $font-12px; + line-height: $font-15px; + color: $secondary-fg-color; + } + + .mx_Checkbox { + display: inline-block; + } + } +} diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss new file mode 100644 index 00000000000..97d5237f041 --- /dev/null +++ b/res/css/structures/_SpaceRoomView.scss @@ -0,0 +1,336 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +$SpaceRoomViewInnerWidth: 428px; + +.mx_SpaceRoomView { + .mx_MainSplit > div:first-child { + padding: 80px 60px; + flex-grow: 1; + + h1 { + margin: 0; + font-size: $font-24px; + font-weight: $font-semi-bold; + color: $primary-fg-color; + width: max-content; + } + + .mx_SpaceRoomView_description { + font-size: $font-15px; + color: $secondary-fg-color; + margin-top: 12px; + margin-bottom: 24px; + } + + .mx_SpaceRoomView_buttons { + display: block; + margin-top: 44px; + width: $SpaceRoomViewInnerWidth; + text-align: right; // button alignment right + + .mx_FormButton { + padding: 8px 22px; + margin-left: 16px; + } + } + + .mx_Field { + max-width: $SpaceRoomViewInnerWidth; + + & + .mx_Field { + margin-top: 28px; + } + } + + .mx_SpaceRoomView_errorText { + font-weight: $font-semi-bold; + font-size: $font-12px; + line-height: $font-15px; + color: $notice-primary-color; + margin-bottom: 28px; + } + + .mx_AccessibleButton_disabled { + cursor: not-allowed; + } + } + + .mx_SpaceRoomView_landing { + overflow-y: auto; + + > .mx_BaseAvatar_image, + > .mx_BaseAvatar > .mx_BaseAvatar_image { + border-radius: 12px; + } + + .mx_SpaceRoomView_landing_name { + margin: 24px 0 16px; + font-size: $font-15px; + color: $secondary-fg-color; + + > span { + display: inline-block; + } + + .mx_SpaceRoomView_landing_nameRow { + margin-top: 12px; + + > h1 { + display: inline-block; + } + } + + .mx_SpaceRoomView_landing_inviter { + .mx_BaseAvatar { + margin-right: 4px; + vertical-align: middle; + } + } + + .mx_SpaceRoomView_landing_memberCount { + position: relative; + margin-left: 24px; + padding: 0 0 0 28px; + line-height: $font-24px; + vertical-align: text-bottom; + + &::before { + position: absolute; + content: ''; + width: 24px; + height: 24px; + top: 0; + left: 0; + mask-position: center; + mask-repeat: no-repeat; + mask-size: contain; + background-color: $accent-color; + mask-image: url('$(res)/img/element-icons/community-members.svg'); + } + } + } + + .mx_SpaceRoomView_landing_topic { + font-size: $font-15px; + } + + .mx_SpaceRoomView_landing_joinButtons { + margin-top: 24px; + + .mx_FormButton { + padding: 8px 22px; + } + } + + .mx_SpaceRoomView_landing_adminButtons { + margin-top: 32px; + + .mx_AccessibleButton { + position: relative; + width: 160px; + height: 124px; + box-sizing: border-box; + padding: 72px 16px 0; + border-radius: 12px; + border: 1px solid $space-button-outline-color; + margin-right: 28px; + margin-bottom: 28px; + font-size: $font-14px; + display: inline-block; + vertical-align: bottom; + + &:last-child { + margin-right: 0; + } + + &:hover { + background-color: rgba(141, 151, 165, 0.1); + } + + &::before, &::after { + position: absolute; + content: ""; + left: 16px; + top: 16px; + height: 40px; + width: 40px; + border-radius: 20px; + } + + &::after { + mask-position: center; + mask-size: 30px; + mask-repeat: no-repeat; + background: #ffffff; // white icon fill + } + + &.mx_SpaceRoomView_landing_inviteButton { + &::before { + background-color: $accent-color; + } + + &::after { + mask-image: url('$(res)/img/element-icons/room/invite.svg'); + } + } + + &.mx_SpaceRoomView_landing_addButton { + &::before { + background-color: #ac3ba8; + } + + &::after { + mask-image: url('$(res)/img/element-icons/roomlist/explore.svg'); + } + } + + &.mx_SpaceRoomView_landing_createButton { + &::before { + background-color: #368bd6; + } + + &::after { + mask-image: url('$(res)/img/element-icons/roomlist/explore.svg'); + } + } + + &.mx_SpaceRoomView_landing_settingsButton { + &::before { + background-color: #5c56f5; + } + + &::after { + mask-image: url('$(res)/img/element-icons/settings.svg'); + } + } + } + } + + .mx_SpaceRoomDirectory_list { + max-width: 600px; + + .mx_SpaceRoomDirectory_roomTile_actions { + display: none; + } + } + } + + .mx_SpaceRoomView_privateScope { + .mx_RadioButton { + width: $SpaceRoomViewInnerWidth; + border-radius: 8px; + border: 1px solid $space-button-outline-color; + padding: 16px 16px 16px 72px; + margin-top: 36px; + cursor: pointer; + box-sizing: border-box; + position: relative; + + > div:first-of-type { + // hide radio dot + display: none; + } + + .mx_RadioButton_content { + margin: 0; + + > h3 { + margin: 0 0 4px; + font-size: $font-15px; + font-weight: $font-semi-bold; + line-height: $font-18px; + } + + > div { + color: $secondary-fg-color; + font-size: $font-15px; + line-height: $font-24px; + } + } + + &::before { + content: ""; + position: absolute; + height: 32px; + width: 32px; + top: 24px; + left: 20px; + background-color: $secondary-fg-color; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + } + } + + .mx_RadioButton_checked { + border-color: $accent-color; + + .mx_RadioButton_content { + > div { + color: $primary-fg-color; + } + } + + &::before { + background-color: $accent-color; + } + } + + .mx_SpaceRoomView_privateScope_justMeButton::before { + mask-image: url('$(res)/img/element-icons/room/members.svg'); + } + + .mx_SpaceRoomView_privateScope_meAndMyTeammatesButton::before { + mask-image: url('$(res)/img/element-icons/community-members.svg'); + } + } + + .mx_SpaceRoomView_inviteTeammates { + .mx_SpaceRoomView_inviteTeammates_buttons { + color: $secondary-fg-color; + margin-top: 28px; + + .mx_AccessibleButton { + position: relative; + display: inline-block; + padding-left: 32px; + line-height: 24px; // to center icons + + &::before { + content: ""; + position: absolute; + height: 24px; + width: 24px; + top: 0; + left: 0; + background-color: $secondary-fg-color; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + } + + & + .mx_AccessibleButton { + margin-left: 32px; + } + } + + .mx_SpaceRoomView_inviteTeammates_inviteDialogButton::before { + mask-image: url('$(res)/img/element-icons/room/invite.svg'); + } + } + } +} diff --git a/res/css/structures/_UserMenu.scss b/res/css/structures/_UserMenu.scss index 2a4453df707..bc4da27ac29 100644 --- a/res/css/structures/_UserMenu.scss +++ b/res/css/structures/_UserMenu.scss @@ -72,6 +72,7 @@ limitations under the License. position: relative; // to make default avatars work margin-right: 8px; height: 32px; // to remove the unknown 4px gap the browser puts below it + padding: 3px 0; // to align with and without using doubleName .mx_UserMenu_userAvatar { border-radius: 32px; // should match avatar size @@ -176,7 +177,7 @@ limitations under the License. } .mx_UserMenu_contextMenu_header { - padding: 20px; + padding: 16px; // Create a flexbox to organize the header a bit easier display: flex; @@ -186,7 +187,7 @@ limitations under the License. // Create another flexbox of columns to handle large user IDs display: flex; flex-direction: column; - width: calc(100% - 40px); // 40px = 32px theme button + 8px margin to theme button + width: calc(100% - 80px); // 80px = 32px user avatar + 32px theme button + 2* 8px margin each * { // Automatically grow all subelements to fit the container @@ -211,6 +212,19 @@ limitations under the License. } } + .mx_UserMenu_contextMenu_spaceAvatar { + margin-right: 8px; + vertical-align: middle; + } + + img.mx_UserMenu_contextMenu_spaceAvatar, .mx_UserMenu_contextMenu_spaceAvatar > img { + border-radius: 8px; + } + + .mx_UserMenu_contextMenu_userAvatar { + margin-right: 8px; + } + .mx_UserMenu_contextMenu_themeButton { min-width: 32px; max-width: 32px; @@ -250,6 +264,27 @@ limitations under the License. padding: 0; } } + + &.mx_UserMenu_contextMenu_secondaryHeader { + position: relative; + + &::before { + border-top: 1px solid $primary-fg-color; + opacity: 0.1; + content: ''; + + // Counteract the padding problems (width: 100% ignores the 40px padding, + // unless we position it absolutely then it does the right thing). + width: 100%; + position: absolute; + left: 0; + top: 0; + } + } + } + + .mx_IconizedContextMenu_optionList:not(.mx_IconizedContextMenu_optionList_notFirst):nth-child(n + 2)::before { + content: unset !important; // hide the default hairlines from IconizedContextMenu } .mx_IconizedContextMenu_icon { diff --git a/res/css/views/context_menus/_IconizedContextMenu.scss b/res/css/views/context_menus/_IconizedContextMenu.scss index d911ac6dfea..204435995f1 100644 --- a/res/css/views/context_menus/_IconizedContextMenu.scss +++ b/res/css/views/context_menus/_IconizedContextMenu.scss @@ -75,6 +75,11 @@ limitations under the License. background-color: $menu-selected-color; } + &.mx_AccessibleButton_disabled { + opacity: 0.5; + cursor: not-allowed; + } + img, .mx_IconizedContextMenu_icon { // icons width: 16px; min-width: 16px; diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss new file mode 100644 index 00000000000..35b1a232868 --- /dev/null +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss @@ -0,0 +1,185 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_AddExistingToSpaceDialog_wrapper { + .mx_Dialog { + display: flex; + flex-direction: column; + } +} + +.mx_AddExistingToSpaceDialog { + width: 480px; + color: $primary-fg-color; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + min-height: 0; + + .mx_Dialog_title { + display: flex; + + .mx_BaseAvatar { + display: inline-flex; + margin: 5px 16px 5px 5px; + vertical-align: middle; + } + + .mx_BaseAvatar_image { + border-radius: 8px; + margin: 0; + vertical-align: unset; + } + + > div { + > h1 { + font-weight: $font-semi-bold; + font-size: $font-18px; + line-height: $font-22px; + margin: 0; + } + + .mx_AddExistingToSpaceDialog_onlySpace { + color: $secondary-fg-color; + font-size: $font-15px; + line-height: $font-24px; + } + } + + .mx_Dropdown_input { + border: none; + + > .mx_Dropdown_option { + padding-left: 0; + flex: unset; + height: unset; + color: $secondary-fg-color; + font-size: $font-15px; + line-height: $font-24px; + + .mx_BaseAvatar { + display: none; + } + } + + .mx_Dropdown_menu { + .mx_AddExistingToSpaceDialog_dropdownOptionActive { + color: $accent-color; + padding-right: 32px; + position: relative; + + &::before { + content: ''; + width: 20px; + height: 20px; + top: 8px; + right: 0; + position: absolute; + mask-position: center; + mask-size: contain; + mask-repeat: no-repeat; + background-color: $accent-color; + mask-image: url('$(res)/img/element-icons/roomlist/checkmark.svg'); + } + } + } + } + } + + .mx_SearchBox { + margin: 0; + } + + .mx_AddExistingToSpaceDialog_errorText { + font-weight: $font-semi-bold; + font-size: $font-12px; + line-height: $font-15px; + color: $notice-primary-color; + margin-bottom: 28px; + } + + .mx_AddExistingToSpaceDialog_content { + .mx_AddExistingToSpaceDialog_noResults { + margin-top: 24px; + } + } + + .mx_AddExistingToSpaceDialog_section { + margin-top: 24px; + + > h3 { + margin: 0; + color: $secondary-fg-color; + font-size: $font-12px; + font-weight: $font-semi-bold; + line-height: $font-15px; + } + + .mx_AddExistingToSpaceDialog_entry { + display: flex; + margin-top: 12px; + + .mx_BaseAvatar { + margin-right: 12px; + } + + .mx_AddExistingToSpaceDialog_entry_name { + font-size: $font-15px; + line-height: 30px; + flex-grow: 1; + } + + .mx_FormButton { + min-width: 92px; + font-weight: normal; + box-sizing: border-box; + } + } + } + + .mx_AddExistingToSpaceDialog_section_spaces { + .mx_BaseAvatar_image { + border-radius: 8px; + } + } + + .mx_AddExistingToSpaceDialog_footer { + display: flex; + margin-top: 32px; + + > span { + flex-grow: 1; + font-size: $font-12px; + line-height: $font-15px; + + > * { + vertical-align: middle; + } + } + + .mx_AccessibleButton { + display: inline-block; + } + + .mx_AccessibleButton_kind_link { + padding: 0; + } + } + + .mx_FormButton { + padding: 8px 22px; + } +} diff --git a/res/css/views/dialogs/_SpaceSettingsDialog.scss b/res/css/views/dialogs/_SpaceSettingsDialog.scss new file mode 100644 index 00000000000..6b9f3a0ceef --- /dev/null +++ b/res/css/views/dialogs/_SpaceSettingsDialog.scss @@ -0,0 +1,55 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_SpaceSettingsDialog { + width: 480px; + color: $primary-fg-color; + + .mx_SpaceSettings_errorText { + font-weight: $font-semi-bold; + font-size: $font-12px; + line-height: $font-15px; + color: $notice-primary-color; + margin-bottom: 28px; + } + + .mx_ToggleSwitch { + display: inline-block; + vertical-align: middle; + margin-left: 16px; + } + + .mx_AccessibleButton_kind_danger { + margin-top: 28px; + } + + .mx_SpaceSettingsDialog_buttons { + display: flex; + margin-top: 64px; + + .mx_AccessibleButton { + display: inline-block; + } + + .mx_AccessibleButton_kind_link { + margin-left: auto; + } + } + + .mx_FormButton { + padding: 8px 22px; + } +} diff --git a/res/css/views/rooms/_MemberInfo.scss b/res/css/views/rooms/_MemberInfo.scss index 182c280217d..3f7f83d3342 100644 --- a/res/css/views/rooms/_MemberInfo.scss +++ b/res/css/views/rooms/_MemberInfo.scss @@ -19,6 +19,7 @@ limitations under the License. flex-direction: column; flex: 1; overflow-y: auto; + margin-top: 8px; } .mx_MemberInfo_name { diff --git a/res/css/views/rooms/_MemberList.scss b/res/css/views/rooms/_MemberList.scss index 1e3506e3715..631ddc484fd 100644 --- a/res/css/views/rooms/_MemberList.scss +++ b/res/css/views/rooms/_MemberList.scss @@ -44,6 +44,10 @@ limitations under the License. .mx_AutoHideScrollbar { flex: 1 1 0; } + + .mx_RightPanel_scopeHeader { + margin-top: -8px; + } } .mx_GroupMemberList_query, diff --git a/res/css/views/rooms/_RoomList.scss b/res/css/views/rooms/_RoomList.scss index 66e1b827d0f..d49ed4b7369 100644 --- a/res/css/views/rooms/_RoomList.scss +++ b/res/css/views/rooms/_RoomList.scss @@ -19,7 +19,10 @@ limitations under the License. } .mx_RoomList_iconPlus::before { - mask-image: url('$(res)/img/element-icons/roomlist/plus.svg'); + mask-image: url('$(res)/img/element-icons/roomlist/plus-circle.svg'); +} +.mx_RoomList_iconHash::before { + mask-image: url('$(res)/img/element-icons/roomlist/hash-circle.svg'); } .mx_RoomList_iconExplore::before { mask-image: url('$(res)/img/element-icons/roomlist/explore.svg'); diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index 8eca3f1efae..40a270f37ce 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -160,6 +160,12 @@ limitations under the License. margin-right: 0; } } + + &.mx_RoomTile_space { + .mx_BaseAvatar_image { + border-radius: 8px; + } + } } // We use these both in context menus and the room tiles diff --git a/res/css/views/spaces/_SpaceBasicSettings.scss b/res/css/views/spaces/_SpaceBasicSettings.scss new file mode 100644 index 00000000000..3a4525d1c8d --- /dev/null +++ b/res/css/views/spaces/_SpaceBasicSettings.scss @@ -0,0 +1,86 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_SpaceBasicSettings { + .mx_Field { + margin: 32px 0; + } + + .mx_SpaceBasicSettings_avatarContainer { + display: flex; + margin-top: 24px; + + .mx_SpaceBasicSettings_avatar { + position: relative; + height: 80px; + width: 80px; + background-color: $tertiary-fg-color; + border-radius: 16px; + } + + img.mx_SpaceBasicSettings_avatar { + width: 80px; + height: 80px; + object-fit: cover; + border-radius: 16px; + } + + // only show it when the button is a div and not an img (has avatar) + div.mx_SpaceBasicSettings_avatar { + cursor: pointer; + + &::before { + content: ""; + position: absolute; + height: 80px; + width: 80px; + top: 0; + left: 0; + background-color: #ffffff; // white icon fill + mask-repeat: no-repeat; + mask-position: center; + mask-size: 20px; + mask-image: url('$(res)/img/element-icons/camera.svg'); + } + } + + > input[type="file"] { + display: none; + } + + > .mx_AccessibleButton_kind_link { + display: inline-block; + padding: 0; + margin: auto 16px; + color: #368bd6; + } + + > .mx_SpaceBasicSettings_avatar_remove { + color: $notice-primary-color; + } + } + + .mx_FormButton { + padding: 8px 22px; + margin-left: auto; + display: block; + width: min-content; + } + + .mx_AccessibleButton_disabled { + cursor: not-allowed; + } +} diff --git a/res/css/views/spaces/_SpaceCreateMenu.scss b/res/css/views/spaces/_SpaceCreateMenu.scss new file mode 100644 index 00000000000..a6597e2d47f --- /dev/null +++ b/res/css/views/spaces/_SpaceCreateMenu.scss @@ -0,0 +1,138 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// TODO: the space panel currently does not have a fixed width, +// just the headers at each level have a max-width of 150px +// so this will look slightly off for now. We should probably use css grid for the whole main layout... +$spacePanelWidth: 200px; + +.mx_SpaceCreateMenu_wrapper { + // background blur everything except SpacePanel + .mx_ContextualMenu_background { + background-color: $dialog-backdrop-color; + opacity: 0.6; + left: $spacePanelWidth; + } + + .mx_ContextualMenu { + padding: 24px; + width: 480px; + box-sizing: border-box; + background-color: $primary-bg-color; + + > div { + > h2 { + font-weight: $font-semi-bold; + font-size: $font-18px; + margin-top: 4px; + } + + > p { + font-size: $font-15px; + color: $secondary-fg-color; + margin: 0; + } + } + + .mx_SpaceCreateMenuType { + position: relative; + padding: 16px 32px 16px 72px; + width: 432px; + box-sizing: border-box; + border-radius: 8px; + border: 1px solid $input-darker-bg-color; + font-size: $font-15px; + margin: 20px 0; + + > h3 { + font-weight: $font-semi-bold; + margin: 0 0 4px; + } + + > span { + color: $secondary-fg-color; + } + + &::before { + position: absolute; + content: ''; + width: 32px; + height: 32px; + top: 24px; + left: 20px; + mask-position: center; + mask-repeat: no-repeat; + mask-size: 32px; + background-color: $tertiary-fg-color; + } + + &:hover { + border-color: $accent-color; + + &::before { + background-color: $accent-color; + } + + > span { + color: $primary-fg-color; + } + } + } + + .mx_SpaceCreateMenuType_public::before { + mask-image: url('$(res)/img/globe.svg'); + mask-size: 26px; + } + .mx_SpaceCreateMenuType_private::before { + mask-image: url('$(res)/img/element-icons/lock.svg'); + } + + .mx_SpaceCreateMenu_back { + width: 28px; + height: 28px; + position: relative; + background-color: $theme-button-bg-color; + border-radius: 14px; + margin-bottom: 12px; + + &::before { + content: ""; + position: absolute; + height: 28px; + width: 28px; + top: 0; + left: 0; + background-color: $muted-fg-color; + transform: rotate(90deg); + mask-repeat: no-repeat; + mask-position: 2px 3px; + mask-size: 24px; + mask-image: url('$(res)/img/feather-customised/chevron-down.svg'); + } + } + + .mx_FormButton { + padding: 8px 22px; + margin-left: auto; + display: block; + width: min-content; + } + + .mx_AccessibleButton_disabled { + cursor: not-allowed; + } + } +} diff --git a/res/css/views/spaces/_SpacePublicShare.scss b/res/css/views/spaces/_SpacePublicShare.scss new file mode 100644 index 00000000000..f47e840fd1d --- /dev/null +++ b/res/css/views/spaces/_SpacePublicShare.scss @@ -0,0 +1,60 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_SpacePublicShare { + .mx_AccessibleButton { + border: 1px solid $space-button-outline-color; + box-sizing: border-box; + border-radius: 8px; + padding: 12px 24px 12px 52px; + margin-top: 16px; + width: $SpaceRoomViewInnerWidth; + font-size: $font-15px; + line-height: $font-24px; + position: relative; + display: flex; + + > span { + color: #368bd6; + margin-left: auto; + } + + &:hover { + background-color: rgba(141, 151, 165, 0.1); + } + + &::before { + content: ""; + position: absolute; + width: 30px; + height: 30px; + mask-repeat: no-repeat; + mask-size: contain; + mask-position: center; + background: $muted-fg-color; + left: 12px; + top: 9px; + } + + &.mx_SpacePublicShare_shareButton::before { + mask-image: url('$(res)/img/element-icons/link.svg'); + } + + &.mx_SpacePublicShare_inviteButton::before { + mask-image: url('$(res)/img/element-icons/room/invite.svg'); + } + } +} diff --git a/res/img/element-icons/expand-space-panel.svg b/res/img/element-icons/expand-space-panel.svg new file mode 100644 index 00000000000..11232acd581 --- /dev/null +++ b/res/img/element-icons/expand-space-panel.svg @@ -0,0 +1,4 @@ + + + + diff --git a/res/img/element-icons/link.svg b/res/img/element-icons/link.svg new file mode 100644 index 00000000000..ab3d54b838e --- /dev/null +++ b/res/img/element-icons/link.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/element-icons/lock.svg b/res/img/element-icons/lock.svg new file mode 100644 index 00000000000..06fe52a3918 --- /dev/null +++ b/res/img/element-icons/lock.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/element-icons/plus.svg b/res/img/element-icons/plus.svg new file mode 100644 index 00000000000..ea1972237d1 --- /dev/null +++ b/res/img/element-icons/plus.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/element-icons/room/invite.svg b/res/img/element-icons/room/invite.svg index 655f9f118a7..d2ecb837b23 100644 --- a/res/img/element-icons/room/invite.svg +++ b/res/img/element-icons/room/invite.svg @@ -1,3 +1,3 @@ - + diff --git a/res/img/element-icons/roomlist/hash-circle.svg b/res/img/element-icons/roomlist/hash-circle.svg new file mode 100644 index 00000000000..924b22cf329 --- /dev/null +++ b/res/img/element-icons/roomlist/hash-circle.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/res/img/element-icons/roomlist/plus-circle.svg b/res/img/element-icons/roomlist/plus-circle.svg new file mode 100644 index 00000000000..251ded225cf --- /dev/null +++ b/res/img/element-icons/roomlist/plus-circle.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index a878aa3cddb..0de5e697820 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -123,6 +123,7 @@ $roomsublist-divider-color: $primary-fg-color; $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #3e444c 0%, #3e444c00 100%); $groupFilterPanel-divider-color: $roomlist-header-color; +$space-button-outline-color: rgba(141, 151, 165, 0.2); $roomtile-preview-color: $secondary-fg-color; $roomtile-default-badge-bg-color: #61708b; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 3e3c299af95..8c5f20178bb 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -120,6 +120,7 @@ $roomsublist-divider-color: $primary-fg-color; $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #3e444c 0%, #3e444c00 100%); $groupFilterPanel-divider-color: $roomlist-header-color; +$space-button-outline-color: rgba(141, 151, 165, 0.2); $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index a740ba155cb..3ba10a68eae 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -187,6 +187,7 @@ $roomsublist-divider-color: $primary-fg-color; $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%); $groupFilterPanel-divider-color: $roomlist-header-color; +$space-button-outline-color: #E3E8F0; $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 1c89d83c018..76bf2ddc216 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -181,6 +181,7 @@ $roomsublist-divider-color: $primary-fg-color; $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%); $groupFilterPanel-divider-color: $roomlist-header-color; +$space-button-outline-color: #E3E8F0; $roomtile-preview-color: $secondary-fg-color; $roomtile-default-badge-bg-color: #61708b; diff --git a/res/themes/light/css/_mods.scss b/res/themes/light/css/_mods.scss index 30aaeedf8fe..fbca58dfb1e 100644 --- a/res/themes/light/css/_mods.scss +++ b/res/themes/light/css/_mods.scss @@ -16,6 +16,10 @@ backdrop-filter: blur($groupFilterPanel-background-blur-amount); } + .mx_SpacePanel { + backdrop-filter: blur($groupFilterPanel-background-blur-amount); + } + .mx_LeftPanel .mx_LeftPanel_roomListContainer { backdrop-filter: blur($roomlist-background-blur-amount); } diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 28f22780a2f..4aa6df54889 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -38,6 +38,7 @@ import UserActivity from "../UserActivity"; import {ModalWidgetStore} from "../stores/ModalWidgetStore"; import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore"; import VoipUserMapper from "../VoipUserMapper"; +import {SpaceStoreClass} from "../stores/SpaceStore"; declare global { interface Window { @@ -68,6 +69,7 @@ declare global { mxUserActivity: UserActivity; mxModalWidgetStore: ModalWidgetStore; mxVoipUserMapper: VoipUserMapper; + mxSpaceStore: SpaceStoreClass; } interface Document { diff --git a/src/Avatar.ts b/src/Avatar.ts index 60bdfdcf753..e2557e21a88 100644 --- a/src/Avatar.ts +++ b/src/Avatar.ts @@ -165,6 +165,9 @@ export function avatarUrlForRoom(room: Room, width: number, height: number, resi return explicitRoomAvatar; } + // space rooms cannot be DMs so skip the rest + if (room.isSpaceRoom()) return null; + let otherMember = null; const otherUserId = DMRoomMap.shared().getUserIdForRoomId(room.roomId); if (otherUserId) { diff --git a/src/RoomInvite.js b/src/RoomInvite.js index 06d3fb04e88..728ae11e794 100644 --- a/src/RoomInvite.js +++ b/src/RoomInvite.js @@ -22,7 +22,7 @@ import MultiInviter from './utils/MultiInviter'; import Modal from './Modal'; import * as sdk from './'; import { _t } from './languageHandler'; -import {KIND_DM, KIND_INVITE} from "./components/views/dialogs/InviteDialog"; +import InviteDialog, {KIND_DM, KIND_INVITE, KIND_SPACE_INVITE} from "./components/views/dialogs/InviteDialog"; import CommunityPrototypeInviteDialog from "./components/views/dialogs/CommunityPrototypeInviteDialog"; import {CommunityPrototypeStore} from "./stores/CommunityPrototypeStore"; @@ -75,6 +75,13 @@ export function showCommunityInviteDialog(communityId) { } } +export const showSpaceInviteDialog = (roomId) => { + Modal.createTrackedDialog("Invite Users", "Space", InviteDialog, { + kind: KIND_SPACE_INVITE, + roomId, + }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); +}; + /** * Checks if the given MatrixEvent is a valid 3rd party user invite. * @param {MatrixEvent} event The event to check diff --git a/src/accessibility/context_menu/MenuItem.tsx b/src/accessibility/context_menu/MenuItem.tsx index 0bb169abf82..9a7c1d1f0ae 100644 --- a/src/accessibility/context_menu/MenuItem.tsx +++ b/src/accessibility/context_menu/MenuItem.tsx @@ -19,14 +19,23 @@ limitations under the License. import React from "react"; import AccessibleButton from "../../components/views/elements/AccessibleButton"; +import AccessibleTooltipButton from "../../components/views/elements/AccessibleTooltipButton"; interface IProps extends React.ComponentProps { label?: string; + tooltip?: string; } // Semantic component for representing a role=menuitem -export const MenuItem: React.FC = ({children, label, ...props}) => { +export const MenuItem: React.FC = ({children, label, tooltip, ...props}) => { const ariaLabel = props["aria-label"] || label; + + if (tooltip) { + return + { children } + ; + } + return ( { children } diff --git a/src/components/structures/ContextMenu.tsx b/src/components/structures/ContextMenu.tsx index aab7701f26f..dd4b596f4d3 100644 --- a/src/components/structures/ContextMenu.tsx +++ b/src/components/structures/ContextMenu.tsx @@ -76,6 +76,7 @@ export interface IProps extends IPosition { hasBackground?: boolean; // whether this context menu should be focus managed. If false it must handle itself managed?: boolean; + wrapperClassName?: string; // Function to be called on menu close onFinished(); @@ -365,7 +366,7 @@ export class ContextMenu extends React.PureComponent { return (
{ } // Placement method for to position context menu to right of elementRect with chevronOffset -export const toRightOf = (elementRect: DOMRect, chevronOffset = 12) => { +export const toRightOf = (elementRect: Pick, chevronOffset = 12) => { const left = elementRect.right + window.pageXOffset + 3; let top = elementRect.top + (elementRect.height / 2) + window.pageYOffset; top -= chevronOffset + 8; // where 8 is half the height of the chevron diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index 4445ff3ff84..82dd9443cc3 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -39,6 +39,7 @@ import { OwnProfileStore } from "../../stores/OwnProfileStore"; import { MatrixClientPeg } from "../../MatrixClientPeg"; import RoomListNumResults from "../views/rooms/RoomListNumResults"; import LeftPanelWidget from "./LeftPanelWidget"; +import SpacePanel from "../views/spaces/SpacePanel"; interface IProps { isMinimized: boolean; @@ -388,12 +389,19 @@ export default class LeftPanel extends React.Component { } public render(): React.ReactNode { - const groupFilterPanel = !this.state.showGroupFilterPanel ? null : ( -
- - {SettingsStore.getValue("feature_custom_tags") ? : null} -
- ); + let leftLeftPanel; + // Currently TagPanel.enableTagPanel is disabled when Legacy Communities are disabled so for now + // ignore it and force the rendering of SpacePanel if that Labs flag is enabled. + if (SettingsStore.getValue("feature_spaces")) { + leftLeftPanel = ; + } else if (this.state.showGroupFilterPanel) { + leftLeftPanel = ( +
+ + {SettingsStore.getValue("feature_custom_tags") ? : null} +
+ ); + } const roomList = { const containerClasses = classNames({ "mx_LeftPanel": true, - "mx_LeftPanel_hasGroupFilterPanel": !!groupFilterPanel, "mx_LeftPanel_minimized": this.props.isMinimized, }); @@ -417,7 +424,7 @@ export default class LeftPanel extends React.Component { return (
- {groupFilterPanel} + {leftLeftPanel}