Skip to content

Commit

Permalink
fix: change editor menu position on large viewport (#857)
Browse files Browse the repository at this point in the history
  • Loading branch information
amanharwara committed Feb 10, 2022
1 parent 78ec092 commit 3b830b0
Showing 1 changed file with 100 additions and 73 deletions.
173 changes: 100 additions & 73 deletions app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx
Expand Up @@ -27,7 +27,7 @@ import {
TransactionalMutation,
} from '@standardnotes/snjs';
import { FunctionComponent } from 'preact';
import { useEffect, useRef, useState } from 'preact/hooks';
import { useEffect, useLayoutEffect, useRef, useState } from 'preact/hooks';
import { Icon } from '../Icon';
import { createEditorMenuGroups } from './changeEditor/createEditorMenuGroups';
import { EditorAccordionMenu } from './changeEditor/EditorAccordionMenu';
Expand All @@ -54,22 +54,99 @@ export type 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> = ({
application,
appState,
closeOnBlur,
note,
}) => {
const [changeEditorMenuOpen, setChangeEditorMenuOpen] = useState(false);
const [changeEditorMenuPosition, setChangeEditorMenuPosition] = useState<{
top?: number | 'auto';
right?: number | 'auto';
bottom: number | 'auto';
left?: number | 'auto';
}>({
right: 0,
bottom: 0,
});
const [changeEditorMenuPosition, setChangeEditorMenuPosition] =
useState<MenuPositionStyle>({
right: 0,
bottom: 0,
});
const changeEditorMenuRef = useRef<HTMLDivElement>(null);
const changeEditorButtonRef = useRef<HTMLButtonElement>(null);
const [editors] = useState<SNComponent[]>(() =>
Expand All @@ -95,78 +172,28 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
}, [application, note]);

const toggleChangeEditorMenu = () => {
const defaultFontSize = window.getComputedStyle(
document.documentElement
).fontSize;
const maxChangeEditorMenuSize =
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,
});
if (!changeEditorMenuOpen) {
const menuPosition = calculateMenuPosition(changeEditorButtonRef.current);
if (menuPosition) {
setChangeEditorMenuPosition(menuPosition);
}
}

setChangeEditorMenuOpen(!changeEditorMenuOpen);
};

useEffect(() => {
useLayoutEffect(() => {
if (changeEditorMenuOpen) {
const defaultFontSize = window.getComputedStyle(
document.documentElement
).fontSize;
const maxChangeEditorMenuSize =
parseFloat(defaultFontSize) * MAX_MENU_SIZE_MULTIPLIER;
const changeEditorMenuBoundingRect =
changeEditorMenuRef.current?.getBoundingClientRect();
const buttonRect = changeEditorButtonRef.current?.getBoundingClientRect();

if (changeEditorMenuBoundingRect && buttonRect) {
if (changeEditorMenuBoundingRect.y < MENU_MARGIN_FROM_APP_BORDER) {
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',
});
}
}
const newMenuPosition = calculateMenuPosition(
changeEditorButtonRef.current,
changeEditorMenuRef.current
);

if (newMenuPosition) {
setChangeEditorMenuPosition(newMenuPosition);
}
}
}, [changeEditorMenuOpen, changeEditorMenuPosition]);
}, [changeEditorMenuOpen]);

const selectComponent = async (component: SNComponent | null) => {
if (component) {
Expand Down

0 comments on commit 3b830b0

Please sign in to comment.