Add description to context menu + Improve context menu position and size

This commit is contained in:
Eric NGUYEN 2022-10-04 16:30:55 +02:00
parent 84f968a872
commit cc84e59701
4 changed files with 31 additions and 8 deletions

View file

@ -38,6 +38,7 @@ function InitActions(
'elements-sidebar-row', 'elements-sidebar-row',
[{ [{
text: 'Delete', text: 'Delete',
title: 'Delete the container',
action: (target: HTMLElement) => { action: (target: HTMLElement) => {
const id = target.id; const id = target.id;
const newHistory = DeleteContainer( const newHistory = DeleteContainer(
@ -53,6 +54,7 @@ function InitActions(
'symbols-sidebar-row', 'symbols-sidebar-row',
[{ [{
text: 'Delete', text: 'Delete',
title: 'Delete the container',
action: (target: HTMLElement) => { action: (target: HTMLElement) => {
const id = target.id; const id = target.id;
const newHistory = DeleteSymbol( const newHistory = DeleteSymbol(
@ -83,6 +85,7 @@ function InitActions(
const currentState = GetCurrentHistoryState(history, historyCurrentStep); const currentState = GetCurrentHistoryState(history, historyCurrentStep);
const newAction: IMenuAction = { const newAction: IMenuAction = {
text: action.Label, text: action.Label,
title: action.Description,
action: GetAction( action: GetAction(
action, action,
currentState, currentState,
@ -320,7 +323,7 @@ export function Editor(props: IEditorProps): JSX.Element {
<Menu <Menu
getListener={() => editorRef.current} getListener={() => editorRef.current}
actions={menuActions} actions={menuActions}
className="z-30 transition-opacity rounded bg-slate-200 py-1 drop-shadow-xl" className="z-30 transition-opacity rounded bg-slate-200 drop-shadow-xl"
/> />
</div> </div>
); );

View file

@ -1,3 +1,4 @@
import useSize from '@react-hook/size';
import * as React from 'react'; import * as React from 'react';
import { IPoint } from '../../Interfaces/IPoint'; import { IPoint } from '../../Interfaces/IPoint';
import { MenuItem } from './MenuItem'; import { MenuItem } from './MenuItem';
@ -12,6 +13,9 @@ export interface IMenuAction {
/** displayed */ /** displayed */
text: string text: string
/** title to show on hover */
title?: string
/** function to be called on button click */ /** function to be called on button click */
action: (target: HTMLElement) => void action: (target: HTMLElement) => void
} }
@ -60,6 +64,9 @@ function UseMouseEvents(
}); });
} }
const MENU_WIDTH_CLASS = 'w-52';
const MENU_VERTICAL_PADDING_CLASS = 'py-1';
export function Menu(props: IMenuProps): JSX.Element { export function Menu(props: IMenuProps): JSX.Element {
const [isOpen, setIsOpen] = React.useState(false); const [isOpen, setIsOpen] = React.useState(false);
const [contextMenuPosition, setContextMenuPosition] = React.useState<IPoint>({ const [contextMenuPosition, setContextMenuPosition] = React.useState<IPoint>({
@ -67,6 +74,8 @@ export function Menu(props: IMenuProps): JSX.Element {
y: 0 y: 0
}); });
const [target, setTarget] = React.useState<HTMLElement>(); const [target, setTarget] = React.useState<HTMLElement>();
const menuRef = React.useRef<HTMLDivElement>(null);
const [menuWidth, menuHeight] = useSize(menuRef);
UseMouseEvents( UseMouseEvents(
props.getListener, props.getListener,
@ -89,21 +98,26 @@ export function Menu(props: IMenuProps): JSX.Element {
actions.forEach((action, index) => { actions.forEach((action, index) => {
children.push(<MenuItem children.push(<MenuItem
key={`contextmenu-item-${count}-${index}`} key={`contextmenu-item-${count}-${index}`}
className="contextmenu-item" className={'contextmenu-item'}
text={action.text} text={action.text}
title={action.title}
onClick={() => action.action(target)} />); onClick={() => action.action(target)} />);
}); });
}; };
} }
// TODO: Fix css const visible = isOpen && children.length > 0 ? 'visible opacity-1' : 'invisible opacity-0';
const visible = isOpen ? 'visible opacity-1' : 'invisible opacity-0'; const isOutOfBoundHorizontally = contextMenuPosition.x + menuWidth > window.innerWidth;
const isOutOfBoundVertically = contextMenuPosition.y + menuHeight > window.innerHeight;
const finalHorizontalPosition = isOutOfBoundHorizontally ? contextMenuPosition.x - menuWidth : contextMenuPosition.x;
const finalVerticalPosition = isOutOfBoundVertically ? contextMenuPosition.y - menuWidth : contextMenuPosition.y;
return ( return (
<div <div
className={`fixed ${props.className ?? ''} ${visible}`} ref={menuRef}
className={`fixed context-menu ${MENU_VERTICAL_PADDING_CLASS} ${MENU_WIDTH_CLASS} ${props.className ?? ''} ${visible}`}
style={{ style={{
left: contextMenuPosition.x, left: finalHorizontalPosition,
top: contextMenuPosition.y top: finalVerticalPosition
}}> }}>
{ children } { children }
</div> </div>

View file

@ -3,6 +3,7 @@ import * as React from 'react';
interface IMenuItemProps { interface IMenuItemProps {
className?: string className?: string
text: string text: string
title?: string
onClick: () => void onClick: () => void
} }
@ -10,6 +11,7 @@ export function MenuItem(props: IMenuItemProps): JSX.Element {
return ( return (
<button type="button" <button type="button"
className={props.className} className={props.className}
title={props.title}
onClick={() => props.onClick()}>{props.text} onClick={() => props.onClick()}>{props.text}
</button> </button>
); );

View file

@ -109,8 +109,12 @@
transition-all duration-100 scale-0 origin-left transition-all duration-100 scale-0 origin-left
} }
.contextmenu {
@apply grid grid-cols-1 gap-0
}
.contextmenu-item { .contextmenu-item {
@apply px-2 py-1 hover:bg-slate-300 text-left @apply px-2 py-1 hover:bg-slate-300 text-left w-full
} }
.input-group { .input-group {