diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index 22cc4f33e9..5603de18d8 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -32,6 +32,10 @@ $roomListCollapsedWidth: 68px; display: flex; overflow: hidden; position: relative; + + &[data-collapsed] { + max-width: $roomListCollapsedWidth; + } } } @@ -40,12 +44,12 @@ $roomListCollapsedWidth: 68px; .mx_LeftPanel { background-color: $roomlist-bg-color; // TODO decrease this once Spaces launches as it'll no longer need to include the 56px Community Panel - min-width: 206px; // Create a row-based flexbox for the GroupFilterPanel and the room list display: flex; contain: content; position: relative; + flex-grow: 1; // Note: The 'room list' in this context is actually everything that isn't the tag // panel, such as the menu options, breadcrumbs, filtering, etc @@ -178,6 +182,8 @@ $roomListCollapsedWidth: 68px; } .mx_LeftPanel_roomListWrapper { + // Make the y-scrollbar more responsive + padding-right: 2px; overflow: hidden; margin-top: 10px; // so we're not up against the search/filter flex: 1 0 0; // needed in Safari to properly set flex-basis @@ -199,6 +205,7 @@ $roomListCollapsedWidth: 68px; // These styles override the defaults for the minimized (66px) layout &.mx_LeftPanel_minimized { + flex-grow: 0; min-width: unset; width: unset !important; diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 457000dbb8..bbe0e42a0a 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -151,7 +151,8 @@ class LoggedInView extends React.Component { private dispatcherRef: string; protected readonly _matrixClient: MatrixClient; protected readonly _roomView: React.RefObject; - protected readonly _resizeContainer: React.RefObject; + protected readonly _resizeContainer: React.RefObject; + protected readonly resizeHandler: React.RefObject; protected compactLayoutWatcherRef: string; protected backgroundImageWatcherRef: string; protected resizer: Resizer; @@ -176,6 +177,7 @@ class LoggedInView extends React.Component { this._roomView = React.createRef(); this._resizeContainer = React.createRef(); + this.resizeHandler = React.createRef(); } componentDidMount() { @@ -280,6 +282,7 @@ class LoggedInView extends React.Component { isItemCollapsed: domNode => { return domNode.classList.contains("mx_LeftPanel_minimized"); }, + handler: this.resizeHandler.current, }; const resizer = new Resizer(this._resizeContainer.current, CollapseDistributor, collapseConfig); resizer.setClassNames({ @@ -681,16 +684,17 @@ class LoggedInView extends React.Component { backgroundImage={this.state.backgroundImage} />
-
+
{ pageElement }
diff --git a/src/components/views/elements/ResizeHandle.js b/src/components/views/elements/ResizeHandle.tsx similarity index 54% rename from src/components/views/elements/ResizeHandle.js rename to src/components/views/elements/ResizeHandle.tsx index 578689b45c..5ca4cadb54 100644 --- a/src/components/views/elements/ResizeHandle.js +++ b/src/components/views/elements/ResizeHandle.tsx @@ -1,27 +1,27 @@ import React from 'react'; // eslint-disable-line no-unused-vars -import PropTypes from 'prop-types'; //see src/resizer for the actual resizing code, this is just the DOM for the resize handle -const ResizeHandle = (props) => { +interface IResizeHandleProps { + vertical?: boolean; + reverse?: boolean; + id?: string; + passRef?: React.RefObject; +} + +const ResizeHandle: React.FC = ({ vertical, reverse, id, passRef }) => { const classNames = ['mx_ResizeHandle']; - if (props.vertical) { + if (vertical) { classNames.push('mx_ResizeHandle_vertical'); } else { classNames.push('mx_ResizeHandle_horizontal'); } - if (props.reverse) { + if (reverse) { classNames.push('mx_ResizeHandle_reverse'); } return ( -
+
); }; -ResizeHandle.propTypes = { - vertical: PropTypes.bool, - reverse: PropTypes.bool, - id: PropTypes.string, -}; - export default ResizeHandle; diff --git a/src/resizer/distributors/collapse.ts b/src/resizer/distributors/collapse.ts index d39580667c..1cef94976d 100644 --- a/src/resizer/distributors/collapse.ts +++ b/src/resizer/distributors/collapse.ts @@ -40,8 +40,13 @@ class CollapseItem extends ResizeItem { } export default class CollapseDistributor extends FixedDistributor { - static createItem(resizeHandle: HTMLDivElement, resizer: Resizer, sizer: Sizer) { - return new CollapseItem(resizeHandle, resizer, sizer); + static createItem( + resizeHandle: HTMLDivElement, + resizer: Resizer, + sizer: Sizer, + container?: HTMLElement, + ): CollapseItem { + return new CollapseItem(resizeHandle, resizer, sizer, container); } private readonly toggleSize: number; @@ -55,12 +60,9 @@ export default class CollapseDistributor extends FixedDistributor { handle: HTMLElement, public readonly resizer: Resizer, public readonly sizer: Sizer, + public readonly container?: HTMLElement, ) { this.reverse = resizer.isReverseResizeHandle(handle); - this.domNode = (this.reverse ? handle.nextElementSibling : handle.previousElementSibling); + if (container) { + this.domNode = (container); + } else { + this.domNode = (this.reverse ? handle.nextElementSibling : handle.previousElementSibling); + } this.id = handle.getAttribute("data-id"); } - private copyWith(handle: HTMLElement, resizer: Resizer, sizer: Sizer) { + private copyWith(handle: HTMLElement, resizer: Resizer, sizer: Sizer, container?: HTMLElement) { const Ctor = this.constructor as typeof ResizeItem; - return new Ctor(handle, resizer, sizer); + return new Ctor(handle, resizer, sizer, container); } private advance(forwards: boolean) { diff --git a/src/resizer/resizer.ts b/src/resizer/resizer.ts index 0496615188..92f458e7c7 100644 --- a/src/resizer/resizer.ts +++ b/src/resizer/resizer.ts @@ -35,6 +35,7 @@ export interface IConfig { onResizeStart?(): void; onResizeStop?(): void; onResized?(size: number, id: string, element: HTMLElement): void; + handler?: HTMLDivElement; } export default class Resizer { @@ -46,8 +47,17 @@ export default class Resizer { public container: HTMLElement, private readonly distributorCtor: { new(item: ResizeItem): FixedDistributor; - createItem(resizeHandle: HTMLDivElement, resizer: Resizer, sizer: Sizer): ResizeItem; - createSizer(containerElement: HTMLElement, vertical: boolean, reverse: boolean): Sizer; + createItem( + resizeHandle: HTMLDivElement, + resizer: Resizer, + sizer: Sizer, + container: HTMLElement + ): ResizeItem; + createSizer( + containerElement: HTMLElement, + vertical: boolean, + reverse: boolean + ): Sizer; }, public readonly config?: C, ) { @@ -68,12 +78,14 @@ export default class Resizer { } public attach() { - this.container.addEventListener("mousedown", this.onMouseDown, false); + const attachment = this?.config?.handler.parentElement ?? this.container; + attachment.addEventListener("mousedown", this.onMouseDown, false); window.addEventListener("resize", this.onResize); } public detach() { - this.container.removeEventListener("mousedown", this.onMouseDown, false); + const attachment = this?.config?.handler.parentElement ?? this.container; + attachment.removeEventListener("mousedown", this.onMouseDown, false); window.removeEventListener("resize", this.onResize); } @@ -113,7 +125,8 @@ export default class Resizer { // use closest in case the resize handle contains // child dom nodes that can be the target const resizeHandle = event.target && (event.target).closest(`.${this.classNames.handle}`); - if (!resizeHandle || resizeHandle.parentElement !== this.container) { + const hasHandler = this?.config?.handler; + if (!resizeHandle || (!hasHandler && resizeHandle.parentElement !== this.container)) { return; } // prevent starting a drag operation @@ -174,13 +187,17 @@ export default class Resizer { const vertical = resizeHandle.classList.contains(this.classNames.vertical); const reverse = this.isReverseResizeHandle(resizeHandle); const Distributor = this.distributorCtor; + const useItemContainer = this.config && this.config.handler ? this.container : undefined; const sizer = Distributor.createSizer(this.container, vertical, reverse); - const item = Distributor.createItem(resizeHandle, this, sizer); + const item = Distributor.createItem(resizeHandle, this, sizer, useItemContainer); const distributor = new Distributor(item); return { sizer, distributor }; } private getResizeHandles() { + if (this?.config?.handler) { + return [this.config.handler]; + } if (!this.container.children) return []; return Array.from(this.container.querySelectorAll(`.${this.classNames.handle}`)) as HTMLElement[]; }