fix: change editor menu position on large viewport (#857)
This commit is contained in:
@@ -27,7 +27,7 @@ import {
|
|||||||
TransactionalMutation,
|
TransactionalMutation,
|
||||||
} from '@standardnotes/snjs';
|
} from '@standardnotes/snjs';
|
||||||
import { FunctionComponent } from 'preact';
|
import { FunctionComponent } from 'preact';
|
||||||
import { useEffect, useRef, useState } from 'preact/hooks';
|
import { useEffect, useLayoutEffect, useRef, useState } from 'preact/hooks';
|
||||||
import { Icon } from '../Icon';
|
import { Icon } from '../Icon';
|
||||||
import { createEditorMenuGroups } from './changeEditor/createEditorMenuGroups';
|
import { createEditorMenuGroups } from './changeEditor/createEditorMenuGroups';
|
||||||
import { EditorAccordionMenu } from './changeEditor/EditorAccordionMenu';
|
import { EditorAccordionMenu } from './changeEditor/EditorAccordionMenu';
|
||||||
@@ -54,6 +54,87 @@ export type EditorMenuItem = {
|
|||||||
|
|
||||||
export type EditorMenuGroup = AccordionMenuGroup<EditorMenuItem>;
|
export type EditorMenuGroup = AccordionMenuGroup<EditorMenuItem>;
|
||||||
|
|
||||||
|
type MenuPositionStyle = {
|
||||||
|
top?: number | 'auto';
|
||||||
|
right?: number | 'auto';
|
||||||
|
bottom: number | 'auto';
|
||||||
|
left?: number | 'auto';
|
||||||
|
};
|
||||||
|
|
||||||
|
const calculateMenuPosition = (
|
||||||
|
button: HTMLButtonElement | null,
|
||||||
|
menu?: HTMLDivElement | null
|
||||||
|
): MenuPositionStyle | undefined => {
|
||||||
|
const defaultFontSize = window.getComputedStyle(
|
||||||
|
document.documentElement
|
||||||
|
).fontSize;
|
||||||
|
|
||||||
|
const maxChangeEditorMenuSize =
|
||||||
|
parseFloat(defaultFontSize) * MAX_MENU_SIZE_MULTIPLIER;
|
||||||
|
|
||||||
|
const { clientWidth, clientHeight } = document.documentElement;
|
||||||
|
|
||||||
|
const buttonRect = button?.getBoundingClientRect();
|
||||||
|
|
||||||
|
const buttonParentRect = button?.parentElement?.getBoundingClientRect();
|
||||||
|
|
||||||
|
const menuBoundingRect = menu?.getBoundingClientRect();
|
||||||
|
|
||||||
|
const footerElementRect = document
|
||||||
|
.getElementById('footer-bar')
|
||||||
|
?.getBoundingClientRect();
|
||||||
|
|
||||||
|
const footerHeightInPx = footerElementRect?.height ?? 0;
|
||||||
|
|
||||||
|
let position: MenuPositionStyle = {
|
||||||
|
bottom: 'auto',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (buttonRect && buttonParentRect) {
|
||||||
|
let positionBottom =
|
||||||
|
clientHeight - buttonRect.bottom - buttonRect.height / 2;
|
||||||
|
|
||||||
|
if (positionBottom < footerHeightInPx) {
|
||||||
|
positionBottom = footerHeightInPx + MENU_MARGIN_FROM_APP_BORDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonRect.right + maxChangeEditorMenuSize > clientWidth) {
|
||||||
|
position = {
|
||||||
|
bottom: positionBottom,
|
||||||
|
right: clientWidth - buttonRect.left,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
position = {
|
||||||
|
bottom: positionBottom,
|
||||||
|
left: buttonRect.right,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (menuBoundingRect && buttonRect) {
|
||||||
|
if (menuBoundingRect.y < MENU_MARGIN_FROM_APP_BORDER) {
|
||||||
|
if (
|
||||||
|
buttonRect.right + maxChangeEditorMenuSize >
|
||||||
|
document.documentElement.clientWidth
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
...position,
|
||||||
|
top: MENU_MARGIN_FROM_APP_BORDER + buttonRect.top - buttonRect.height,
|
||||||
|
bottom: 'auto',
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...position,
|
||||||
|
top: MENU_MARGIN_FROM_APP_BORDER,
|
||||||
|
bottom: 'auto',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
|
export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
|
||||||
application,
|
application,
|
||||||
appState,
|
appState,
|
||||||
@@ -61,12 +142,8 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
|
|||||||
note,
|
note,
|
||||||
}) => {
|
}) => {
|
||||||
const [changeEditorMenuOpen, setChangeEditorMenuOpen] = useState(false);
|
const [changeEditorMenuOpen, setChangeEditorMenuOpen] = useState(false);
|
||||||
const [changeEditorMenuPosition, setChangeEditorMenuPosition] = useState<{
|
const [changeEditorMenuPosition, setChangeEditorMenuPosition] =
|
||||||
top?: number | 'auto';
|
useState<MenuPositionStyle>({
|
||||||
right?: number | 'auto';
|
|
||||||
bottom: number | 'auto';
|
|
||||||
left?: number | 'auto';
|
|
||||||
}>({
|
|
||||||
right: 0,
|
right: 0,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
});
|
});
|
||||||
@@ -95,78 +172,28 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
|
|||||||
}, [application, note]);
|
}, [application, note]);
|
||||||
|
|
||||||
const toggleChangeEditorMenu = () => {
|
const toggleChangeEditorMenu = () => {
|
||||||
const defaultFontSize = window.getComputedStyle(
|
if (!changeEditorMenuOpen) {
|
||||||
document.documentElement
|
const menuPosition = calculateMenuPosition(changeEditorButtonRef.current);
|
||||||
).fontSize;
|
if (menuPosition) {
|
||||||
const maxChangeEditorMenuSize =
|
setChangeEditorMenuPosition(menuPosition);
|
||||||
parseFloat(defaultFontSize) * MAX_MENU_SIZE_MULTIPLIER;
|
|
||||||
const { clientWidth, clientHeight } = document.documentElement;
|
|
||||||
const buttonRect = changeEditorButtonRef.current?.getBoundingClientRect();
|
|
||||||
const buttonParentRect =
|
|
||||||
changeEditorButtonRef.current?.parentElement?.getBoundingClientRect();
|
|
||||||
const footerElementRect = document
|
|
||||||
.getElementById('footer-bar')
|
|
||||||
?.getBoundingClientRect();
|
|
||||||
const footerHeightInPx = footerElementRect?.height;
|
|
||||||
|
|
||||||
if (buttonRect && buttonParentRect && footerHeightInPx) {
|
|
||||||
let positionBottom =
|
|
||||||
clientHeight - buttonRect.bottom - buttonRect.height / 2;
|
|
||||||
|
|
||||||
if (positionBottom < footerHeightInPx) {
|
|
||||||
positionBottom = footerHeightInPx + MENU_MARGIN_FROM_APP_BORDER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buttonRect.right + maxChangeEditorMenuSize > clientWidth) {
|
|
||||||
setChangeEditorMenuPosition({
|
|
||||||
top: positionBottom - buttonParentRect.height / 2,
|
|
||||||
right: clientWidth - buttonRect.left,
|
|
||||||
bottom: 'auto',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setChangeEditorMenuPosition({
|
|
||||||
bottom: positionBottom,
|
|
||||||
left: buttonRect.right,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setChangeEditorMenuOpen(!changeEditorMenuOpen);
|
setChangeEditorMenuOpen(!changeEditorMenuOpen);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (changeEditorMenuOpen) {
|
if (changeEditorMenuOpen) {
|
||||||
const defaultFontSize = window.getComputedStyle(
|
const newMenuPosition = calculateMenuPosition(
|
||||||
document.documentElement
|
changeEditorButtonRef.current,
|
||||||
).fontSize;
|
changeEditorMenuRef.current
|
||||||
const maxChangeEditorMenuSize =
|
);
|
||||||
parseFloat(defaultFontSize) * MAX_MENU_SIZE_MULTIPLIER;
|
|
||||||
const changeEditorMenuBoundingRect =
|
|
||||||
changeEditorMenuRef.current?.getBoundingClientRect();
|
|
||||||
const buttonRect = changeEditorButtonRef.current?.getBoundingClientRect();
|
|
||||||
|
|
||||||
if (changeEditorMenuBoundingRect && buttonRect) {
|
if (newMenuPosition) {
|
||||||
if (changeEditorMenuBoundingRect.y < MENU_MARGIN_FROM_APP_BORDER) {
|
setChangeEditorMenuPosition(newMenuPosition);
|
||||||
if (
|
|
||||||
buttonRect.right + maxChangeEditorMenuSize >
|
|
||||||
document.documentElement.clientWidth
|
|
||||||
) {
|
|
||||||
setChangeEditorMenuPosition({
|
|
||||||
...changeEditorMenuPosition,
|
|
||||||
top: MENU_MARGIN_FROM_APP_BORDER + buttonRect.height,
|
|
||||||
bottom: 'auto',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setChangeEditorMenuPosition({
|
|
||||||
...changeEditorMenuPosition,
|
|
||||||
top: MENU_MARGIN_FROM_APP_BORDER,
|
|
||||||
bottom: 'auto',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}, [changeEditorMenuOpen]);
|
||||||
}
|
|
||||||
}, [changeEditorMenuOpen, changeEditorMenuPosition]);
|
|
||||||
|
|
||||||
const selectComponent = async (component: SNComponent | null) => {
|
const selectComponent = async (component: SNComponent | null) => {
|
||||||
if (component) {
|
if (component) {
|
||||||
|
|||||||
Reference in New Issue
Block a user