feat: added node-tooltips to the editor
This commit is contained in:
committed by
Björn Otgaar
parent
5385bd72b1
commit
566c4c18cc
@@ -1,7 +1,12 @@
|
||||
import { NodeToolbar } from '@xyflow/react';
|
||||
import {NodeToolbar} from '@xyflow/react';
|
||||
import '@xyflow/react/dist/style.css';
|
||||
import {type JSX, useState} from "react";
|
||||
import {createPortal} from "react-dom";
|
||||
import styles from "../../VisProg.module.css";
|
||||
import {NodeTooltips} from "../NodeRegistry.ts";
|
||||
import useFlowStore from "../VisProgStores.tsx";
|
||||
|
||||
|
||||
/**
|
||||
* Props for the Toolbar component.
|
||||
*
|
||||
@@ -24,14 +29,94 @@ type ToolbarProps = {
|
||||
* @constructor
|
||||
*/
|
||||
export function Toolbar({nodeId, allowDelete}: ToolbarProps) {
|
||||
const {deleteNode} = useFlowStore();
|
||||
const {nodes, deleteNode} = useFlowStore();
|
||||
|
||||
const deleteParentNode = ()=> {
|
||||
|
||||
const deleteParentNode = () => {
|
||||
deleteNode(nodeId);
|
||||
}
|
||||
};
|
||||
|
||||
const nodeType = nodes.find((node) => node.id === nodeId)?.type as keyof typeof NodeTooltips;
|
||||
return (
|
||||
<NodeToolbar>
|
||||
<NodeToolbar className={"flex-row align-center"}>
|
||||
<button className="Node-toolbar__deletebutton" onClick={deleteParentNode} disabled={!allowDelete}>delete</button>
|
||||
<Tooltip nodeType={nodeType}>
|
||||
<div className={styles.nodeToolbarTooltip}>i</div>
|
||||
</Tooltip>
|
||||
</NodeToolbar>);
|
||||
}
|
||||
|
||||
|
||||
type TooltipProps = {
|
||||
nodeType?: keyof typeof NodeTooltips;
|
||||
children: JSX.Element;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A general tooltip component, that can be used as a wrapper for any component
|
||||
* that has a nodeType and a corresponding nodeTooltip.
|
||||
*
|
||||
* currently used to show tooltips for draggable-nodes and nodes inside the editor
|
||||
*
|
||||
* @param {"start" | "end" | "phase" | "norm" | "goal" | "trigger" | "basic_belief" | undefined} nodeType
|
||||
* @param {React.JSX.Element} children
|
||||
* @returns {React.JSX.Element}
|
||||
* @constructor
|
||||
*/
|
||||
export function Tooltip({ nodeType, children }: TooltipProps) {
|
||||
const [showTooltip, setShowTooltip] = useState(false);
|
||||
const [disabled , setDisabled] = useState(false);
|
||||
const [coords, setCoords] = useState({ top: 0, left: 0 });
|
||||
|
||||
const updateTooltipPos = () => {
|
||||
const rect = document.getElementById("draggable-sidebar")!.getBoundingClientRect();
|
||||
setCoords({
|
||||
// Position exactly below the bottom edge of the draggable sidebar (plus a small gap)
|
||||
top: rect.bottom + 10,
|
||||
left: rect.left + rect.width / 2, // Keep it horizontally centered
|
||||
});
|
||||
};
|
||||
|
||||
return nodeType ?
|
||||
(<div>
|
||||
<div
|
||||
onMouseDown={() => {
|
||||
updateTooltipPos();
|
||||
setShowTooltip(false);
|
||||
setDisabled(true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
setDisabled(false);
|
||||
}}
|
||||
onMouseOver={() => {
|
||||
if (!disabled) {
|
||||
updateTooltipPos();
|
||||
setShowTooltip(true);
|
||||
}
|
||||
}}
|
||||
onMouseLeave={ () => setShowTooltip(false)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
{showTooltip && createPortal(
|
||||
<div
|
||||
className={"flex-row"}
|
||||
style={{
|
||||
pointerEvents: 'none',
|
||||
position: 'fixed',
|
||||
top: `${coords.top}px`,
|
||||
left: `${coords.left}px`,
|
||||
transform: 'translateX(-50%)', // Center based on the midpoint
|
||||
}}
|
||||
>
|
||||
<span className={styles.customTooltipHeader}>{nodeType}</span>
|
||||
<span className={styles.customTooltip}>
|
||||
{NodeTooltips[nodeType] || "Available for drag"}
|
||||
</span>
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
</div>
|
||||
) : children
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user