Skip to content

Commit

Permalink
feat: use improved style calculation for change editor submenu (#899)
Browse files Browse the repository at this point in the history
  • Loading branch information
amanharwara authored Feb 25, 2022
1 parent c3d849d commit 4db8ca8
Showing 1 changed file with 16 additions and 125 deletions.
141 changes: 16 additions & 125 deletions app/assets/javascripts/components/NotesOptions/ChangeEditorOption.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { KeyboardKey } from '@/services/ioService';
import { WebApplication } from '@/ui_models/application';
import { AppState } from '@/ui_models/app_state';
import {
MENU_MARGIN_FROM_APP_BORDER,
MAX_MENU_SIZE_MULTIPLIER,
} from '@/constants';
import {
Disclosure,
DisclosureButton,
Expand All @@ -21,6 +17,10 @@ import { useEffect, useRef, useState } from 'preact/hooks';
import { Icon } from '../Icon';
import { createEditorMenuGroups } from './changeEditor/createEditorMenuGroups';
import { ChangeEditorMenu } from './changeEditor/ChangeEditorMenu';
import {
calculateSubmenuStyle,
SubmenuStyle,
} from '@/utils/calculateSubmenuStyle';

type ChangeEditorOptionProps = {
appState: AppState;
Expand All @@ -44,107 +44,18 @@ export type EditorMenuItem = {

export type EditorMenuGroup = AccordionMenuGroup<EditorMenuItem>;

type MenuPositionStyle = {
top?: number | 'auto';
right?: number | 'auto';
bottom: number | 'auto';
left?: number | 'auto';
visibility?: 'hidden' | 'visible';
};

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,
visibility: 'hidden',
};
} else {
position = {
bottom: positionBottom,
left: buttonRect.right,
visibility: 'hidden',
};
}
}

if (menuBoundingRect && menuBoundingRect.height && 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',
visibility: 'visible',
};
} else {
return {
...position,
top: MENU_MARGIN_FROM_APP_BORDER,
bottom: 'auto',
visibility: 'visible',
};
}
}
}

return position;
};

export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
application,
closeOnBlur,
note,
}) => {
const [changeEditorMenuOpen, setChangeEditorMenuOpen] = useState(false);
const [changeEditorMenuVisible, setChangeEditorMenuVisible] = useState(false);
const [changeEditorMenuMaxHeight, setChangeEditorMenuMaxHeight] = useState<
number | 'auto'
>('auto');
const [changeEditorMenuPosition, setChangeEditorMenuPosition] =
useState<MenuPositionStyle>({
right: 0,
bottom: 0,
});
const [menuStyle, setMenuStyle] = useState<SubmenuStyle>({
right: 0,
bottom: 0,
maxHeight: 'auto',
});
const changeEditorMenuRef = useRef<HTMLDivElement>(null);
const changeEditorButtonRef = useRef<HTMLButtonElement>(null);
const [editors] = useState<SNComponent[]>(() =>
Expand All @@ -171,9 +82,9 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({

const toggleChangeEditorMenu = () => {
if (!changeEditorMenuOpen) {
const menuPosition = calculateMenuPosition(changeEditorButtonRef.current);
if (menuPosition) {
setChangeEditorMenuPosition(menuPosition);
const menuStyle = calculateSubmenuStyle(changeEditorButtonRef.current);
if (menuStyle) {
setMenuStyle(menuStyle);
}
}

Expand All @@ -183,32 +94,13 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
useEffect(() => {
if (changeEditorMenuOpen) {
setTimeout(() => {
const newMenuPosition = calculateMenuPosition(
const newMenuStyle = calculateSubmenuStyle(
changeEditorButtonRef.current,
changeEditorMenuRef.current
);

if (newMenuPosition) {
const { clientHeight } = document.documentElement;
const footerElementRect = document
.getElementById('footer-bar')
?.getBoundingClientRect();
const footerHeightInPx = footerElementRect?.height;

if (
footerHeightInPx &&
newMenuPosition.top &&
newMenuPosition.top !== 'auto'
) {
setChangeEditorMenuMaxHeight(
clientHeight -
newMenuPosition.top -
footerHeightInPx -
MENU_MARGIN_FROM_APP_BORDER
);
}

setChangeEditorMenuPosition(newMenuPosition);
if (newMenuStyle) {
setMenuStyle(newMenuStyle);
setChangeEditorMenuVisible(true);
}
});
Expand Down Expand Up @@ -242,8 +134,7 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
}
}}
style={{
...changeEditorMenuPosition,
maxHeight: changeEditorMenuMaxHeight,
...menuStyle,
position: 'fixed',
}}
className="sn-dropdown flex flex-col max-h-120 min-w-68 fixed overflow-y-auto"
Expand Down

0 comments on commit 4db8ca8

Please sign in to comment.