Add description to context menu + Improve context menu position and size
This commit is contained in:
parent
84f968a872
commit
cc84e59701
4 changed files with 31 additions and 8 deletions
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue