/* 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_RoomSublist { margin-left: 8px; margin-bottom: 4px; &.mx_RoomSublist_hidden { display: none; } &:not(.mx_RoomSublist_minimized) { .mx_RoomSublist_headerContainer { height: auto; } } .mx_RoomSublist_headerContainer { /* Create a flexbox to make alignment easy */ display: flex; align-items: center; /* *************************** */ /* Sticky Headers Start */ /* Ideally we'd be able to use `position: sticky; top: 0; bottom: 0;` on the */ /* headerContainer, however due to our layout concerns we actually have to */ /* calculate it manually so we can sticky things in the right places. We also */ /* target the headerText instead of the container to reduce jumps when scrolling, */ /* and to help hide the badges/other buttons that could appear on hover. This */ /* all works by ensuring the header text has a fixed height when sticky so the */ /* fixed height of the container can maintain the scroll position. */ /* The combined height must be set in the LeftPanel component for sticky headers */ /* to work correctly. */ padding-bottom: 8px; height: 24px; color: $tertiary-content; .mx_RoomSublist_stickableContainer { width: 100%; } .mx_RoomSublist_stickable { flex: 1; max-width: 100%; /* Create a flexbox to make ordering easy */ display: flex; align-items: center; /* We use a generic sticky class for 2 reasons: to reduce style duplication and */ /* to identify when a header is sticky. If we didn't have a consistent sticky class, */ /* we'd have to do the "is sticky" checks again on click, as clicking the header */ /* when sticky scrolls instead of collapses the list. */ &.mx_RoomSublist_headerContainer_sticky { position: fixed; height: 32px; /* to match the header container */ /* width set by JS because of a compat issue between Firefox and Chrome */ width: calc(100% - 15px); } /* We don't have a top style because the top is dependent on the room list header's */ /* height, and is therefore calculated in JS. */ /* The class, mx_RoomSublist_headerContainer_stickyTop, is applied though. */ } /* Sticky Headers End */ /* *************************** */ .mx_RoomSublist_badgeContainer { /* Create another flexbox row because it's super easy to position the badge this way. */ display: flex; align-items: center; justify-content: center; /* Apply the width and margin to the badge so the container doesn't occupy dead space */ .mx_NotificationBadge { /* Do not set a width so the badges get properly sized */ margin-left: 8px; /* same as menu+aux buttons */ } } &:not(.mx_RoomSublist_headerContainer_withAux) { .mx_NotificationBadge { margin-right: 4px; /* just to push it over a bit, aligning it with the other elements */ } } .mx_RoomSublist_auxButton, .mx_RoomSublist_menuButton { margin-left: 8px; /* should be the same as the notification badge */ position: relative; width: 24px; height: 24px; border-radius: 8px; &::before { content: ""; width: 16px; height: 16px; position: absolute; top: 4px; left: 4px; mask-position: center; mask-size: contain; mask-repeat: no-repeat; background: $muted-fg-color; } } .mx_RoomSublist_auxButton:hover, .mx_RoomSublist_menuButton:hover { background: $panel-actions; } /* Hide the menu button by default */ .mx_RoomSublist_menuButton { visibility: hidden; width: 0; margin: 0; } .mx_RoomSublist_auxButton::before { mask-image: url("$(res)/img/element-icons/roomlist/plus.svg"); } .mx_RoomSublist_menuButton::before { mask-image: url("$(res)/img/element-icons/context-menu.svg"); } .mx_RoomSublist_headerText { flex: 1; max-width: calc(100% - 16px); /* 16px is the badge width */ line-height: $font-16px; font-size: $font-13px; font-weight: var(--font-semi-bold); /* Ellipsize any text overflow */ text-overflow: ellipsis; overflow: hidden; white-space: nowrap; .mx_RoomSublist_collapseBtn { display: inline-block; position: relative; width: 14px; height: 14px; margin-right: 6px; &::before { content: ""; width: 18px; height: 18px; position: absolute; mask-position: center; mask-size: contain; mask-repeat: no-repeat; background-color: $tertiary-content; mask-image: url("$(res)/img/feather-customised/chevron-down.svg"); } &.mx_RoomSublist_collapseBtn_collapsed::before { transform: rotate(-90deg); } } } } /* In the general case, we reserve space for each sublist header to prevent */ /* scroll jumps when they become sticky. However, that leaves a gap when */ /* scrolled to the top above the first sublist (whose header can only ever */ /* stick to top), so we make sure to exclude the first visible sublist. */ &:not(.mx_RoomSublist_hidden) ~ .mx_RoomSublist .mx_RoomSublist_stickableContainer { height: 24px; } .mx_RoomSublist_resizeBox { position: relative; /* Create another flexbox column for the tiles */ display: flex; flex-direction: column; overflow: hidden; .mx_RoomSublist_tiles { flex: 1 0 0; overflow: hidden; overflow: clip; /* need this to be flex otherwise the overflow hidden from above */ /* sometimes vertically centers the clipped list ... no idea why it would do this */ /* as the box model should be top aligned. Happens in both FF and Chromium */ display: flex; flex-direction: column; align-self: stretch; /* without this Firefox will prefer pushing the resizer & show more/less button into the overflow */ min-height: 0; mask-image: linear-gradient(0deg, transparent, black 4px); } &.mx_RoomSublist_resizeBox_forceExpanded .mx_RoomSublist_tiles { /* in this state the div can collapse its height entirely in Chromium, */ /* so prevent that by allowing overflow */ overflow: visible; /* clear the min-height to make it not collapse entirely in a state with no active resizer */ min-height: unset; } .mx_RoomSublist_resizerHandles_showNButton { flex: 0 0 32px; } .mx_RoomSublist_resizerHandles { flex: 0 0 4px; display: flex; justify-content: center; width: 100%; } /* Class name comes from the ResizableBox component */ /* The hover state needs to use the whole sublist, not just the resizable box, */ /* so that selector is below and one level higher. */ .mx_RoomSublist_resizerHandle { cursor: ns-resize; border-radius: 3px; /* Override styles from library */ max-width: 64px; height: 4px !important; /* Update RESIZE_HANDLE_HEIGHT if this changes */ /* This is positioned directly below the 'show more' button. */ position: relative !important; bottom: 0 !important; /* override from library */ } &:hover, &.mx_RoomSublist_hasMenuOpen { .mx_RoomSublist_resizerHandle { opacity: 0.8; background-color: $primary-content; } } } .mx_RoomSublist_showNButton { cursor: pointer; font-size: $font-13px; line-height: $font-18px; color: $secondary-content; /* Update the render() function for RoomSublist if these change */ /* Update the ListLayout class for minVisibleTiles if these change. */ height: 24px; padding-bottom: 4px; /* We create a flexbox to cheat at alignment */ display: flex; align-items: center; .mx_RoomSublist_showNButtonChevron { position: relative; width: 18px; height: 18px; margin-left: 12px; margin-right: 16px; mask-position: center; mask-size: contain; mask-repeat: no-repeat; background: $tertiary-content; left: -1px; /* adjust for image position */ } .mx_RoomSublist_showMoreButtonChevron, .mx_RoomSublist_showLessButtonChevron { mask-image: url("$(res)/img/feather-customised/chevron-down.svg"); } .mx_RoomSublist_showLessButtonChevron { transform: rotate(180deg); } } &.mx_RoomSublist_hasMenuOpen, &:not(.mx_RoomSublist_minimized) > .mx_RoomSublist_headerContainer:focus-within, &:not(.mx_RoomSublist_minimized) > .mx_RoomSublist_headerContainer:hover { .mx_RoomSublist_menuButton { visibility: visible; width: 24px; margin-left: 8px; } } &.mx_RoomSublist_minimized { .mx_RoomSublist_headerContainer { height: auto; flex-direction: column; position: relative; .mx_RoomSublist_badgeContainer { order: 0; align-self: flex-end; margin-right: 0; } .mx_RoomSublist_stickable { order: 1; max-width: 100%; } .mx_RoomSublist_auxButton { order: 2; visibility: visible; width: 32px !important; /* !important to override hover styles */ height: 32px !important; /* !important to override hover styles */ margin-left: 0 !important; /* !important to override hover styles */ background-color: $panel-actions; margin-top: 8px; &::before { top: 8px; left: 8px; } } } .mx_RoomSublist_resizeBox { align-items: center; } .mx_RoomSublist_showNButton { flex-direction: column; .mx_RoomSublist_showNButtonChevron { margin-right: 12px; /* to center */ } } .mx_RoomSublist_menuButton { height: 16px; } &.mx_RoomSublist_hasMenuOpen, & > .mx_RoomSublist_headerContainer:hover { .mx_RoomSublist_menuButton { visibility: visible; position: absolute; bottom: 48px; /* align to middle of name, 40px for aux button (with padding) and 8px for alignment */ right: 0; width: 16px; height: 16px; border-radius: 0; z-index: 1; /* occlude the list name */ /* This is the same color as the left panel background because it needs */ /* to occlude the sublist title */ background-color: $roomlist-bg-color; &::before { top: 0; left: 0; } } &.mx_RoomSublist_headerContainer:not(.mx_RoomSublist_headerContainer_withAux) { .mx_RoomSublist_menuButton { bottom: 8px; /* align to the middle of name, 40px less than the `bottom` above. */ } } } } } .mx_RoomSublist_contextMenu { padding: 20px 16px; width: 250px; hr { margin-top: 16px; margin-bottom: 16px; margin-right: 16px; /* additional 16px */ border: 1px solid $primary-content; opacity: 0.1; } .mx_RoomSublist_contextMenu_title { font-size: $font-15px; line-height: $font-20px; font-weight: var(--font-semi-bold); margin-bottom: 4px; } .mx_StyledRadioButton, .mx_Checkbox { margin-top: 8px; } } .mx_RoomSublist_skeletonUI { position: relative; margin-left: 4px; height: 240px; &::before { background: $roomsublist-skeleton-ui-bg; width: 100%; height: 100%; content: ""; position: absolute; mask-repeat: repeat-y; mask-size: auto 48px; mask-image: url("$(res)/img/element-icons/roomlist/skeleton-ui.svg"); } } .mx_RoomSublist_minimized .mx_RoomSublist_skeletonUI { width: 32px; /* cut off the horizontal lines in the svg */ margin-left: 10px; /* align with sublist + buttons */ }