Fix positioning of the thread context menu (#7918)

This commit is contained in:
Michael Telatynski 2022-03-01 08:32:29 +00:00 committed by GitHub
parent b02d5ecb97
commit 115e17b097
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 38 deletions

View file

@ -260,10 +260,11 @@ export default class ContextMenu extends React.PureComponent<IProps, IState> {
const { windowWidth, windowHeight } = UIStore.instance; const { windowWidth, windowHeight } = UIStore.instance;
if (contextMenuRect) { if (contextMenuRect) {
if (position.top !== undefined) { if (position.top !== undefined) {
position.top = Math.min( let maxTop = windowHeight - WINDOW_PADDING;
position.top, if (!this.props.bottomAligned) {
windowHeight - contextMenuRect.height - WINDOW_PADDING, maxTop -= contextMenuRect.height;
); }
position.top = Math.min(position.top, maxTop);
// Adjust the chevron if necessary // Adjust the chevron if necessary
if (chevronOffset.top !== undefined) { if (chevronOffset.top !== undefined) {
chevronOffset.top = props.chevronOffset + props.top - position.top; chevronOffset.top = props.chevronOffset + props.top - position.top;
@ -278,10 +279,11 @@ export default class ContextMenu extends React.PureComponent<IProps, IState> {
} }
} }
if (position.left !== undefined) { if (position.left !== undefined) {
position.left = Math.min( let maxLeft = windowWidth - WINDOW_PADDING;
position.left, if (!this.props.rightAligned) {
windowWidth - contextMenuRect.width - WINDOW_PADDING, maxLeft -= contextMenuRect.width;
); }
position.left = Math.min(position.left, maxLeft);
if (chevronOffset.left !== undefined) { if (chevronOffset.left !== undefined) {
chevronOffset.left = props.chevronOffset + props.left - position.left; chevronOffset.left = props.chevronOffset + props.left - position.left;
} }

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. 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 { MatrixEvent } from "matrix-js-sdk/src";
import { ButtonEvent } from "../elements/AccessibleButton"; import { ButtonEvent } from "../elements/AccessibleButton";
@ -27,7 +27,6 @@ import { _t } from "../../../languageHandler";
import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from "./IconizedContextMenu"; import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from "./IconizedContextMenu";
import { WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore"; import { WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { useRovingTabIndex } from "../../../accessibility/RovingTabIndex";
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
interface IProps { interface IProps {
@ -36,13 +35,6 @@ interface IProps {
onMenuToggle?: (open: boolean) => void; 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) => { const contextMenuBelow = (elementRect: DOMRect) => {
// align the context menu's icons with the icon which opened the context menu // align the context menu's icons with the icon which opened the context menu
const left = elementRect.left + window.pageXOffset + elementRect.width; const left = elementRect.left + window.pageXOffset + elementRect.width;
@ -51,27 +43,13 @@ const contextMenuBelow = (elementRect: DOMRect) => {
return { left, top, chevronFace }; return { left, top, chevronFace };
}; };
export const RovingThreadListContextMenu: React.FC<IProps> = (props) => { const ThreadListContextMenu: React.FC<IProps> = ({
const [onFocus, isActive, ref] = useRovingTabIndex();
return <ThreadListContextMenu
{...props}
onFocus={onFocus}
tabIndex={isActive ? 0 : -1}
inputRef={ref}
/>;
};
const ThreadListContextMenu: React.FC<IExtendedProps> = ({
mxEvent, mxEvent,
permalinkCreator, permalinkCreator,
onMenuToggle, onMenuToggle,
onFocus,
inputRef,
...props ...props
}) => { }) => {
const [menuDisplayed, _ref, openMenu, closeThreadOptions] = useContextMenu(); const [menuDisplayed, button, openMenu, closeThreadOptions] = useContextMenu();
const button = inputRef ?? _ref; // prefer the ref we receive via props in case we are being controlled
const viewInRoom = useCallback((evt: ButtonEvent): void => { const viewInRoom = useCallback((evt: ButtonEvent): void => {
evt.preventDefault(); evt.preventDefault();
@ -95,11 +73,8 @@ const ThreadListContextMenu: React.FC<IExtendedProps> = ({
}, [mxEvent, closeThreadOptions, permalinkCreator]); }, [mxEvent, closeThreadOptions, permalinkCreator]);
useEffect(() => { useEffect(() => {
if (onMenuToggle) { onMenuToggle?.(menuDisplayed);
onMenuToggle(menuDisplayed); }, [menuDisplayed, onMenuToggle]);
}
onFocus?.();
}, [menuDisplayed, onMenuToggle, onFocus]);
const isMainSplitTimelineShown = !WidgetLayoutStore.instance.hasMaximisedWidget( const isMainSplitTimelineShown = !WidgetLayoutStore.instance.hasMaximisedWidget(
MatrixClientPeg.get().getRoom(mxEvent.getRoomId()), MatrixClientPeg.get().getRoom(mxEvent.getRoomId()),