Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Fix positioning of the thread context menu #7918

Merged
merged 7 commits into from
Mar 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions src/components/structures/ContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,11 @@ export default class ContextMenu extends React.PureComponent<IProps, IState> {
const { windowWidth, windowHeight } = UIStore.instance;
if (contextMenuRect) {
if (position.top !== undefined) {
position.top = Math.min(
position.top,
windowHeight - contextMenuRect.height - WINDOW_PADDING,
);
let maxTop = windowHeight - WINDOW_PADDING;
if (!this.props.bottomAligned) {
maxTop -= contextMenuRect.height;
}
position.top = Math.min(position.top, maxTop);
// Adjust the chevron if necessary
if (chevronOffset.top !== undefined) {
chevronOffset.top = props.chevronOffset + props.top - position.top;
Expand All @@ -278,10 +279,11 @@ export default class ContextMenu extends React.PureComponent<IProps, IState> {
}
}
if (position.left !== undefined) {
position.left = Math.min(
position.left,
windowWidth - contextMenuRect.width - WINDOW_PADDING,
);
let maxLeft = windowWidth - WINDOW_PADDING;
if (!this.props.rightAligned) {
maxLeft -= contextMenuRect.width;
}
position.left = Math.min(position.left, maxLeft);
if (chevronOffset.left !== undefined) {
chevronOffset.left = props.chevronOffset + props.left - position.left;
}
Expand Down
35 changes: 5 additions & 30 deletions src/components/views/context_menus/ThreadListContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React, { RefObject, useCallback, useEffect } from "react";
import React, { useCallback, useEffect } from "react";
import { MatrixEvent } from "matrix-js-sdk/src";

import { ButtonEvent } from "../elements/AccessibleButton";
Expand All @@ -27,7 +27,6 @@ import { _t } from "../../../languageHandler";
import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from "./IconizedContextMenu";
import { WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { useRovingTabIndex } from "../../../accessibility/RovingTabIndex";
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";

interface IProps {
Expand All @@ -36,13 +35,6 @@ interface IProps {
onMenuToggle?: (open: boolean) => void;
}

interface IExtendedProps extends IProps {
// Props for making the button into a roving one
tabIndex?: number;
inputRef?: RefObject<HTMLElement>;
onFocus?(): void;
}

const contextMenuBelow = (elementRect: DOMRect) => {
// align the context menu's icons with the icon which opened the context menu
const left = elementRect.left + window.pageXOffset + elementRect.width;
Expand All @@ -51,27 +43,13 @@ const contextMenuBelow = (elementRect: DOMRect) => {
return { left, top, chevronFace };
};

export const RovingThreadListContextMenu: React.FC<IProps> = (props) => {
const [onFocus, isActive, ref] = useRovingTabIndex();

return <ThreadListContextMenu
{...props}
onFocus={onFocus}
tabIndex={isActive ? 0 : -1}
inputRef={ref}
/>;
};

const ThreadListContextMenu: React.FC<IExtendedProps> = ({
const ThreadListContextMenu: React.FC<IProps> = ({
mxEvent,
permalinkCreator,
onMenuToggle,
onFocus,
inputRef,
...props
}) => {
const [menuDisplayed, _ref, openMenu, closeThreadOptions] = useContextMenu();
const button = inputRef ?? _ref; // prefer the ref we receive via props in case we are being controlled
const [menuDisplayed, button, openMenu, closeThreadOptions] = useContextMenu();

const viewInRoom = useCallback((evt: ButtonEvent): void => {
evt.preventDefault();
Expand All @@ -95,11 +73,8 @@ const ThreadListContextMenu: React.FC<IExtendedProps> = ({
}, [mxEvent, closeThreadOptions, permalinkCreator]);

useEffect(() => {
if (onMenuToggle) {
onMenuToggle(menuDisplayed);
}
onFocus?.();
}, [menuDisplayed, onMenuToggle, onFocus]);
onMenuToggle?.(menuDisplayed);
}, [menuDisplayed, onMenuToggle]);

const isMainSplitTimelineShown = !WidgetLayoutStore.instance.hasMaximisedWidget(
MatrixClientPeg.get().getRoom(mxEvent.getRoomId()),
Expand Down