Move the AutoHideScrollbar to shared components (#33777)

* First version of shared component

* Refactor as a functional component

* Add unit tests and more documentation

* Fix problem where wrappedRef was used by parent before assignment was performed.

* Use the shared component in app/web

* Clean up unused styling

* Added scrollbar-gutters as default styling in shared component

* Make sure the legacy mx_AutoHideScrollbar is set in app/web

* Updated snapshots

* Removing default style, scrollbar-gutter: stable;

* Updated snapshots

* useRef on wrapperRef to avoid loop in rendering

* scrollbar-width does not propagate

* Add AutoHideScrollbar to RoomListView

* Fix Prettier issue

* Updated snapshots

* Updated snapshot after merge

* Fix Sonar issue
This commit is contained in:
rbondesson
2026-06-11 09:08:24 +02:00
committed by GitHub
parent e9a89d9872
commit 8a21fdb127
39 changed files with 17217 additions and 16801 deletions
@@ -20,8 +20,6 @@ Please see LICENSE files in the repository root for full details.
.mx_EmojiPicker_body {
flex: 1;
overflow-y: scroll;
scrollbar-width: thin;
scrollbar-color: rgb(0, 0, 0, 0.2) transparent;
}
.mx_EmojiPicker_header {
@@ -173,6 +171,7 @@ Please see LICENSE files in the repository root for full details.
.mx_EmojiPicker_footer {
border-top: 1px solid $message-action-bar-border-color;
min-height: 72px;
max-height: 72px;
display: flex;
align-items: center;
@@ -1,70 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
Copyright 2018 New Vector Ltd
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import classNames from "classnames";
import React, { type HTMLAttributes, type JSX, type ReactNode, type WheelEvent } from "react";
type DynamicHtmlElementProps<T extends keyof JSX.IntrinsicElements> =
JSX.IntrinsicElements[T] extends HTMLAttributes<object> ? DynamicElementProps<T> : DynamicElementProps<"div">;
type DynamicElementProps<T extends keyof JSX.IntrinsicElements> = Partial<Omit<JSX.IntrinsicElements[T], "ref">>;
export type IProps<T extends keyof JSX.IntrinsicElements> = Omit<DynamicHtmlElementProps<T>, "onScroll"> & {
element: T;
className?: string;
onScroll?: (event: Event) => void;
onWheel?: (event: WheelEvent) => void;
style?: React.CSSProperties;
tabIndex?: number;
wrappedRef?: (ref: HTMLDivElement | null) => void;
children: ReactNode;
};
export default class AutoHideScrollbar<T extends keyof JSX.IntrinsicElements> extends React.Component<IProps<T>> {
public static defaultProps = {
element: "div" as keyof HTMLElementTagNameMap,
};
public readonly containerRef = React.createRef<HTMLDivElement>();
public componentDidMount(): void {
if (this.containerRef.current && this.props.onScroll) {
// Using the passive option to not block the main thread
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
this.containerRef.current.addEventListener("scroll", this.props.onScroll, { passive: true });
}
this.props.wrappedRef?.(this.containerRef.current);
}
public componentWillUnmount(): void {
if (this.containerRef.current && this.props.onScroll) {
this.containerRef.current.removeEventListener("scroll", this.props.onScroll);
}
this.props.wrappedRef?.(null);
}
public render(): React.ReactNode {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { element, className, onScroll, tabIndex, wrappedRef, children, ...otherProps } = this.props;
return React.createElement(
element,
{
...otherProps,
ref: this.containerRef,
className: classNames("mx_AutoHideScrollbar", className),
// Firefox sometimes makes this element focusable due to
// overflow:scroll;, so force it out of tab order by default.
tabIndex: tabIndex ?? -1,
},
children,
);
}
}
@@ -11,12 +11,12 @@ import React from "react";
import sanitizeHtml from "sanitize-html";
import classnames from "classnames";
import { logger } from "matrix-js-sdk/src/logger";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import { _t } from "../../languageHandler";
import dis from "../../dispatcher/dispatcher";
import { MatrixClientPeg } from "../../MatrixClientPeg";
import MatrixClientContext from "../../contexts/MatrixClientContext";
import AutoHideScrollbar from "./AutoHideScrollbar";
import { type ActionPayload } from "../../dispatcher/payloads";
import { Action } from "../../dispatcher/actions.ts";
@@ -121,6 +121,7 @@ export default class EmbeddedPage extends React.PureComponent<IProps, IState> {
const isGuest = client ? client.isGuest() : true;
const className = this.props.className;
const classes = classnames(className, {
mx_AutoHideScrollbar: this.props.scrollbar,
[`${className}_guest`]: isGuest,
[`${className}_loggedIn`]: !!client,
});
@@ -9,8 +9,8 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX } from "react";
import { useContext, useState } from "react";
import { ChatSolidIcon, ExploreIcon, GroupIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import AutoHideScrollbar from "./AutoHideScrollbar";
import { getHomePageUrl } from "../../utils/pages";
import { _t, _tDom } from "../../languageHandler";
import SdkConfig from "../../SdkConfig";
@@ -113,7 +113,7 @@ const HomePage: React.FC<IProps> = ({ justRegistered = false }) => {
}
return (
<AutoHideScrollbar className="mx_HomePage mx_HomePage_default" element="main">
<AutoHideScrollbar className="mx_AutoHideScrollbar mx_HomePage mx_HomePage_default" as="main">
<div className="mx_HomePage_default_wrapper">
{introSection}
<div className="mx_HomePage_default_buttons">
@@ -5,9 +5,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import React, { createRef, type JSX } from "react";
import React, { type JSX } from "react";
import { AutoHideScrollbar, type AutoHideScrollbarProps } from "@element-hq/web-shared-components";
import classNames from "classnames";
import AutoHideScrollbar, { type IProps as AutoHideScrollbarProps } from "./AutoHideScrollbar";
import UIStore, { UI_EVENTS } from "../../stores/UIStore";
export type IProps<T extends keyof JSX.IntrinsicElements> = Omit<AutoHideScrollbarProps<T>, "onWheel" | "element"> & {
@@ -32,7 +33,6 @@ export default class IndicatorScrollbar<T extends keyof JSX.IntrinsicElements> e
IProps<T>,
IState
> {
private autoHideScrollbar = createRef<AutoHideScrollbar<any>>();
private scrollElement?: HTMLDivElement;
private likelyTrackpadUser: boolean | null = null;
private checkAgainForTrackpad = 0; // ts in milliseconds to recheck this._likelyTrackpadUser
@@ -170,7 +170,7 @@ export default class IndicatorScrollbar<T extends keyof JSX.IntrinsicElements> e
public render(): React.ReactNode {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { children, trackHorizontalOverflow, verticalScrollsHorizontally, ...otherProps } = this.props;
const { children, trackHorizontalOverflow, verticalScrollsHorizontally, className, ...otherProps } = this.props;
const leftIndicatorStyle = { left: this.state.leftIndicatorOffset };
const rightIndicatorStyle = { right: this.state.rightIndicatorOffset };
@@ -184,7 +184,7 @@ export default class IndicatorScrollbar<T extends keyof JSX.IntrinsicElements> e
return (
<AutoHideScrollbar
{...otherProps}
ref={this.autoHideScrollbar}
className={classNames("mx_AutoHideScrollbar", className)}
wrappedRef={this.collectScroller}
onWheel={this.onMouseWheel}
>
@@ -329,7 +329,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
<IndicatorScrollbar
role="navigation"
aria-label={_t("a11y|recent_rooms")}
className="mx_LeftPanel_breadcrumbsContainer mx_AutoHideScrollbar"
className="mx_LeftPanel_breadcrumbsContainer"
verticalScrollsHorizontally={true}
>
<RoomBreadcrumbs />
@@ -8,10 +8,10 @@ Please see LICENSE files in the repository root for full details.
import React, { createRef, type CSSProperties, type ReactNode } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import SettingsStore from "../../settings/SettingsStore";
import Timer from "../../utils/Timer";
import AutoHideScrollbar from "./AutoHideScrollbar";
import { getKeyBindingsManager } from "../../KeyBindingsManager";
import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts";
import { SDKContext } from "../../contexts/SDKContext";
@@ -940,7 +940,7 @@ export default class ScrollPanel extends React.Component<IProps> {
<AutoHideScrollbar
wrappedRef={this.collectScroll}
onScroll={this.onScroll}
className={`mx_ScrollPanel ${this.props.className}`}
className={`mx_AutoHideScrollbar mx_ScrollPanel ${this.props.className}`}
style={this.props.style}
>
{this.props.fixedChildren}
@@ -10,9 +10,9 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX } from "react";
import classNames from "classnames";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import { _t } from "../../languageHandler";
import AutoHideScrollbar from "./AutoHideScrollbar";
import { PosthogScreenTracker, type ScreenName } from "../../PosthogTrackers";
import { type NonEmptyArray } from "../../@types/common";
import { RovingAccessibleButton, RovingTabIndexProvider } from "../../accessibility/RovingTabIndex";
@@ -74,7 +74,9 @@ function TabPanel<T extends string>({ tab }: ITabPanelProps<T>): JSX.Element {
id={domIDForTabID(tab.id)}
aria-labelledby={`${domIDForTabID(tab.id)}_label`}
>
<AutoHideScrollbar className="mx_TabbedView_tabPanelContent">{tab.body}</AutoHideScrollbar>
<AutoHideScrollbar className="mx_AutoHideScrollbar mx_TabbedView_tabPanelContent">
{tab.body}
</AutoHideScrollbar>
</div>
);
}
@@ -13,6 +13,7 @@ import { KnownMembership } from "matrix-js-sdk/src/types";
import { sleep } from "matrix-js-sdk/src/utils";
import { logger } from "matrix-js-sdk/src/logger";
import { CheckIcon, ErrorIcon, RestartIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import { _t, _td } from "../../../languageHandler";
import BaseDialog from "./BaseDialog";
@@ -22,7 +23,6 @@ import SpaceStore from "../../../stores/spaces/SpaceStore";
import RoomAvatar from "../avatars/RoomAvatar";
import { getDisplayAliasForRoom } from "../../../Rooms";
import AccessibleButton, { type ButtonEvent } from "../elements/AccessibleButton";
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import DMRoomMap from "../../../utils/DMRoomMap";
import { calculateRoomVia } from "../../../utils/permalinks/Permalinks";
import StyledCheckbox from "../elements/StyledCheckbox";
@@ -142,7 +142,7 @@ export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({
[cli, msc3946ProcessDynamicPredecessor],
);
const scrollRef = useRef<AutoHideScrollbar<"div">>(null);
const scrollRef = useRef<HTMLDivElement | null>(null);
const [scrollState, setScrollState] = useState<IScrollState>({
// these are estimates which update as soon as it mounts
scrollTop: 0,
@@ -300,7 +300,7 @@ export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({
}
const onScroll = (): void => {
const body = scrollRef.current?.containerRef.current;
const body = scrollRef.current;
if (!body) return;
setScrollState({
scrollTop: body.scrollTop,
@@ -309,6 +309,7 @@ export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({
};
const wrappedRef = (body: HTMLDivElement | null): void => {
scrollRef.current = body;
if (!body) return;
setScrollState({
scrollTop: body.scrollTop,
@@ -329,10 +330,9 @@ export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({
autoFocus={true}
/>
<AutoHideScrollbar
className="mx_AddExistingToSpace_content"
className="mx_AutoHideScrollbar mx_AddExistingToSpace_content"
onScroll={onScroll}
wrappedRef={wrappedRef}
ref={scrollRef}
>
{rooms.length > 0 && roomsRenderer
? roomsRenderer(rooms, selectedToAdd, roomsScrollState, onChange)
@@ -24,6 +24,7 @@ import {
} from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { CheckCircleIcon, CircleIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import { _t } from "../../../languageHandler";
import dis from "../../../dispatcher/dispatcher";
@@ -34,7 +35,6 @@ import { avatarUrlForUser } from "../../../Avatar";
import EventTile from "../rooms/EventTile";
import SearchBox from "../../structures/SearchBox";
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import { StaticNotificationState } from "../../../stores/notifications/StaticNotificationState";
import NotificationBadge from "../rooms/NotificationBadge";
import { type RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
@@ -384,7 +384,7 @@ const ForwardDialog: React.FC<IProps> = ({ matrixClient: cli, event, permalinkCr
/>
)}
</RovingTabIndexContext.Consumer>
<AutoHideScrollbar className="mx_ForwardList_content">
<AutoHideScrollbar className="mx_AutoHideScrollbar mx_ForwardList_content">
{rooms.length > 0 ? (
<div className="mx_ForwardList_results">
<TruncatedList
@@ -10,6 +10,7 @@ import React, { useMemo, useState } from "react";
import { Room } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { InfoSolidIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import { _t } from "../../../languageHandler";
import BaseDialog from "./BaseDialog";
@@ -17,7 +18,6 @@ import SearchBox from "../../structures/SearchBox";
import SpaceStore from "../../../stores/spaces/SpaceStore";
import RoomAvatar from "../avatars/RoomAvatar";
import AccessibleButton from "../elements/AccessibleButton";
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import StyledCheckbox from "../elements/StyledCheckbox";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { filterBoolean } from "../../../utils/arrays";
@@ -158,7 +158,7 @@ const ManageRestrictedJoinRuleDialog: React.FC<IProps> = ({ room, selected = [],
onSearch={setQuery}
autoFocus={true}
/>
<AutoHideScrollbar className="mx_ManageRestrictedJoinRuleDialog_content">
<AutoHideScrollbar className="mx_AutoHideScrollbar mx_ManageRestrictedJoinRuleDialog_content">
{filteredSpacesContainingRoom.length > 0 ? (
<div className="mx_ManageRestrictedJoinRuleDialog_section">
<h3>
@@ -10,10 +10,10 @@ Please see LICENSE files in the repository root for full details.
import React, { type Dispatch } from "react";
import { DATA_BY_CATEGORY, getEmojiFromUnicode, type Emoji as IEmoji } from "@matrix-org/emojibase-bindings";
import classNames from "classnames";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import { _t } from "../../../languageHandler";
import * as recent from "../../../emojipicker/recent";
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import Header from "./Header";
import Search from "./Search";
import Preview from "./Preview";
@@ -59,7 +59,7 @@ class EmojiPicker extends React.Component<IProps, IState> {
private readonly memoizedDataByCategory: Record<CategoryKey, IEmoji[]>;
private readonly categories: ICategory[];
private scrollRef = React.createRef<AutoHideScrollbar<"div">>();
private scrollElement: HTMLDivElement | null = null;
public constructor(props: IProps) {
super(props);
@@ -115,7 +115,7 @@ class EmojiPicker extends React.Component<IProps, IState> {
}
private onScroll = (): void => {
const body = this.scrollRef.current?.containerRef.current;
const body = this.scrollElement;
if (!body) return;
this.setState({
scrollTop: body.scrollTop,
@@ -174,7 +174,7 @@ class EmojiPicker extends React.Component<IProps, IState> {
};
private updateVisibility = (): void => {
const body = this.scrollRef.current?.containerRef.current;
const body = this.scrollElement;
if (!body) return;
const rect = body.getBoundingClientRect();
let firstVisibleFound = false;
@@ -213,9 +213,7 @@ class EmojiPicker extends React.Component<IProps, IState> {
};
private scrollToCategory = (category: string): void => {
this.scrollRef.current?.containerRef.current
?.querySelector(`[data-category-id="${category}"]`)
?.scrollIntoView();
this.scrollElement?.querySelector(`[data-category-id="${category}"]`)?.scrollIntoView();
};
private onChangeFilter = (filter: string): void => {
@@ -293,9 +291,7 @@ class EmojiPicker extends React.Component<IProps, IState> {
// Only select emoji if highlight is shown
if (!this.state.showHighlight) return;
const btn = this.scrollRef.current?.containerRef.current?.querySelector<HTMLButtonElement>(
'.mx_EmojiPicker_item_wrapper [tabindex="0"]',
);
const btn = this.scrollElement?.querySelector<HTMLButtonElement>('.mx_EmojiPicker_item_wrapper [tabindex="0"]');
btn?.click();
this.props.onFinished();
};
@@ -357,10 +353,12 @@ class EmojiPicker extends React.Component<IProps, IState> {
/>
<AutoHideScrollbar
id="mx_EmojiPicker_body"
className={classNames("mx_EmojiPicker_body", {
className={classNames("mx_AutoHideScrollbar mx_EmojiPicker_body", {
mx_EmojiPicker_body_showHighlight: this.state.showHighlight,
})}
ref={this.scrollRef}
wrappedRef={(ref) => {
this.scrollElement = ref;
}}
onScroll={this.onScroll}
>
{this.categories.map((category) => {
@@ -11,8 +11,8 @@ import classNames from "classnames";
import { IconButton, Text } from "@vector-im/compound-web";
import CloseIcon from "@vector-im/compound-design-tokens/assets/web/icons/close";
import ChevronLeftIcon from "@vector-im/compound-design-tokens/assets/web/icons/chevron-left";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import { _t } from "../../../languageHandler";
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
import { backLabelForPhase } from "../../../stores/right-panel/RightPanelStorePhases";
@@ -100,7 +100,7 @@ const BaseCard: React.FC<IProps> = ({
}
if (!withoutScrollContainer) {
children = <AutoHideScrollbar>{children}</AutoHideScrollbar>;
children = <AutoHideScrollbar className="mx_AutoHideScrollbar">{children}</AutoHideScrollbar>;
}
const shouldRenderHeader = header || !hideHeaderButtons;
@@ -8,10 +8,10 @@ Please see LICENSE files in the repository root for full details.
import React, { type ReactNode } from "react";
import { type Room } from "matrix-js-sdk/src/matrix";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import AppsDrawer from "./AppsDrawer";
import SettingsStore from "../../../settings/SettingsStore";
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import { UIFeature } from "../../../settings/UIFeature";
import LegacyCallViewForRoom from "../voip/LegacyCallViewForRoom";
import { objectHasDiff } from "../../../utils/objects";
@@ -44,7 +44,7 @@ export default class AuxPanel extends React.Component<IProps> {
}
return (
<AutoHideScrollbar role="region" className="mx_AuxPanel">
<AutoHideScrollbar role="region" className="mx_AutoHideScrollbar mx_AuxPanel">
{this.props.children}
{appsDrawer}
{callView}
@@ -9,12 +9,12 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX, type PropsWithChildren } from "react";
import { type User } from "matrix-js-sdk/src/matrix";
import { Tooltip } from "@vector-im/compound-web";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import ReadReceiptMarker, { type IReadReceiptPosition } from "./ReadReceiptMarker";
import { type IReadReceiptProps } from "./EventTile";
import AccessibleButton from "../elements/AccessibleButton";
import MemberAvatar from "../avatars/MemberAvatar";
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import { formatDate } from "../../../DateUtils";
import { Action } from "../../../dispatcher/actions";
import dis from "../../../dispatcher/dispatcher";
@@ -146,7 +146,7 @@ export function ReadReceiptGroup({
const buttonRect = button.current.getBoundingClientRect();
contextMenu = (
<ContextMenu menuClassName="mx_ReadReceiptGroup_popup" onFinished={closeMenu} {...aboveLeftOf(buttonRect)}>
<AutoHideScrollbar>
<AutoHideScrollbar className="mx_AutoHideScrollbar">
<SectionHeader className="mx_ReadReceiptGroup_title">
{_t("timeline|read_receipt_title", { count: readReceipts.length })}
</SectionHeader>
@@ -8,12 +8,12 @@ Please see LICENSE files in the repository root for full details.
import React, { useEffect, useMemo, useState } from "react";
import { type Room } from "matrix-js-sdk/src/matrix";
import { AutoHideScrollbar } from "@element-hq/web-shared-components";
import { _t } from "../../../languageHandler";
import StyledRadioGroup from "../elements/StyledRadioGroup";
import QueryMatcher from "../../../autocomplete/QueryMatcher";
import SearchBox from "../../structures/SearchBox";
import AutoHideScrollbar from "../../structures/AutoHideScrollbar";
import { Entry } from "../dialogs/AddExistingToSpaceDialog";
import { filterBoolean } from "../../../utils/arrays";
@@ -61,7 +61,7 @@ const SpecificChildrenPicker: React.FC<ISpecificChildrenPickerProps> = ({
onSearch={setQuery}
autoFocus={true}
/>
<AutoHideScrollbar>
<AutoHideScrollbar className="mx_AutoHideScrollbar">
{filteredRooms.map((room) => {
return (
<Entry
@@ -327,7 +327,7 @@ const InnerSpacePanel = React.memo<IInnerSpacePanelProps>(
}
: undefined
}
element="ul"
as="ul"
role="tree"
aria-label={_t("common|spaces")}
>
@@ -3,7 +3,7 @@
exports[`MessagePanel should handle large numbers of hidden events quickly 1`] = `
<DocumentFragment>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel cls"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel cls"
tabindex="-1"
>
<div
@@ -22,7 +22,7 @@ exports[`MessagePanel should handle large numbers of hidden events quickly 1`] =
exports[`MessagePanel should handle lots of membership events quickly 1`] = `
<DocumentFragment>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel cls"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel cls"
tabindex="-1"
>
<div
@@ -137,7 +137,7 @@ exports[`MessagePanel should handle lots of membership events quickly 1`] = `
exports[`MessagePanel should handle lots of room creation events quickly 1`] = `
<DocumentFragment>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel cls"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel cls"
tabindex="-1"
>
<div
@@ -137,7 +137,7 @@ exports[`RoomView for a local room in state ERROR should match the snapshot 1`]
class="mx_RoomView_timeline"
>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
tabindex="-1"
>
<div
@@ -333,7 +333,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
class="mx_RoomView_timeline"
>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
tabindex="-1"
>
<div
@@ -738,7 +738,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
class="mx_RoomView_timeline"
>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
tabindex="-1"
>
<div
@@ -1306,7 +1306,7 @@ exports[`RoomView should hide the composer when hideComposer=true 1`] = `
</div>
</header>
<div
class="mx_AutoHideScrollbar mx_AuxPanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_AuxPanel"
role="region"
tabindex="-1"
>
@@ -1317,7 +1317,7 @@ exports[`RoomView should hide the composer when hideComposer=true 1`] = `
data-testid="timeline"
>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
tabindex="-1"
>
<div
@@ -1376,7 +1376,7 @@ exports[`RoomView should hide the header when hideHeader=true 1`] = `
data-layout="group"
>
<div
class="mx_AutoHideScrollbar mx_AuxPanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_AuxPanel"
role="region"
tabindex="-1"
>
@@ -1387,7 +1387,7 @@ exports[`RoomView should hide the header when hideHeader=true 1`] = `
data-testid="timeline"
>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
tabindex="-1"
>
<div
@@ -1860,7 +1860,7 @@ exports[`RoomView should hide the pinned message banner when hidePinnedMessageBa
</div>
</header>
<div
class="mx_AutoHideScrollbar mx_AuxPanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_AuxPanel"
role="region"
tabindex="-1"
>
@@ -1871,7 +1871,7 @@ exports[`RoomView should hide the pinned message banner when hidePinnedMessageBa
data-testid="timeline"
>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
tabindex="-1"
>
<div
@@ -2344,7 +2344,7 @@ exports[`RoomView should hide the right panel when hideRightPanel=true 1`] = `
</div>
</header>
<div
class="mx_AutoHideScrollbar mx_AuxPanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_AuxPanel"
role="region"
tabindex="-1"
>
@@ -2355,7 +2355,7 @@ exports[`RoomView should hide the right panel when hideRightPanel=true 1`] = `
data-testid="timeline"
>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
tabindex="-1"
>
<div
@@ -2828,7 +2828,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
</div>
</header>
<div
class="mx_AutoHideScrollbar mx_AuxPanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_AuxPanel"
role="region"
tabindex="-1"
>
@@ -3066,7 +3066,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
</div>
</header>
<div
class="mx_AutoHideScrollbar mx_AuxPanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_AuxPanel"
role="region"
tabindex="-1"
>
@@ -3077,7 +3077,7 @@ exports[`RoomView should not display the timeline when the room encryption is lo
data-testid="timeline"
>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
tabindex="-1"
>
<div
@@ -3665,7 +3665,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
class="mx_TimelineCard_timeline"
>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
tabindex="-1"
>
<div
@@ -103,7 +103,7 @@ exports[`<TabbedView /> renders tabs 1`] = `
id="mx_tabpanel_GENERAL"
>
<div
class="mx_AutoHideScrollbar mx_TabbedView_tabPanelContent"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_TabbedView_tabPanelContent"
tabindex="-1"
>
<div>
@@ -63,7 +63,7 @@ exports[`<ManageRestrictedJoinRuleDialog /> should list spaces which are not par
</div>
</div>
<div
class="mx_AutoHideScrollbar mx_ManageRestrictedJoinRuleDialog_content"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ManageRestrictedJoinRuleDialog_content"
tabindex="-1"
>
<div
@@ -276,7 +276,7 @@ exports[`<ManageRestrictedJoinRuleDialog /> should render empty state 1`] = `
</div>
</div>
<div
class="mx_AutoHideScrollbar mx_ManageRestrictedJoinRuleDialog_content"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ManageRestrictedJoinRuleDialog_content"
tabindex="-1"
>
<span
@@ -25,7 +25,7 @@ exports[`<MessageEditHistory /> should match the snapshot 1`] = `
</h1>
</div>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel mx_MessageEditHistoryDialog_scrollPanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel mx_MessageEditHistoryDialog_scrollPanel"
tabindex="-1"
>
<div
@@ -166,7 +166,7 @@ exports[`<MessageEditHistory /> should support events with 1`] = `
</h1>
</div>
<div
class="mx_AutoHideScrollbar mx_ScrollPanel mx_MessageEditHistoryDialog_scrollPanel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_ScrollPanel mx_MessageEditHistoryDialog_scrollPanel"
tabindex="-1"
>
<div
@@ -46,7 +46,7 @@ exports[`<BaseCard /> should close when clicking X button 1`] = `
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<div>
@@ -46,7 +46,7 @@ exports[`<ExtensionsCard /> should render empty state 1`] = `
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<button
@@ -147,7 +147,7 @@ exports[`<ExtensionsCard /> should render widgets 1`] = `
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<button
@@ -46,7 +46,7 @@ exports[`<PinnedMessagesCard /> should show the empty state when there are no pi
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<div
@@ -128,7 +128,7 @@ exports[`<PinnedMessagesCard /> should show two pinned messages 1`] = `
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<div
@@ -356,7 +356,7 @@ exports[`<PinnedMessagesCard /> unpin all should not allow to unpinall 1`] = `
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<div
@@ -42,7 +42,7 @@ exports[`<RoomSummaryCard /> has button to edit topic 1`] = `
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<header
@@ -781,7 +781,7 @@ exports[`<RoomSummaryCard /> renders the room summary 1`] = `
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<header
@@ -1478,7 +1478,7 @@ exports[`<RoomSummaryCard /> renders the room topic in the summary 1`] = `
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<header
@@ -46,7 +46,7 @@ exports[`<UserInfo /> with crypto enabled renders <BasicUserInfo /> 1`] = `
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<div
@@ -348,7 +348,7 @@ exports[`<UserInfo /> with crypto enabled should render a deactivate button for
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<div
@@ -46,7 +46,7 @@ exports[`<ThirdPartyMemberInfo /> should render invite 1`] = `
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<div
@@ -121,7 +121,7 @@ exports[`<ThirdPartyMemberInfo /> should render invite when room in not availabl
</button>
</div>
<div
class="mx_AutoHideScrollbar"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar"
tabindex="-1"
>
<div
@@ -90,7 +90,7 @@ exports[`<AddExistingToSpaceDialog /> looks as expected 1`] = `
</div>
</div>
<div
class="mx_AutoHideScrollbar mx_AddExistingToSpace_content"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_AddExistingToSpace_content"
tabindex="-1"
>
<span
@@ -54,7 +54,7 @@ exports[`<SpacePanel /> should show all activated MetaSpaces in the correct orde
</div>
<ul
aria-label="Spaces"
class="mx_AutoHideScrollbar mx_SpaceTreeLevel"
class="_scrollbar_1d5jg_8 mx_AutoHideScrollbar mx_SpaceTreeLevel"
data-rbd-droppable-context-id="0"
data-rbd-droppable-id="top-level-spaces"
role="tree"