Skip to content

Commit

Permalink
feat: Card tooltip (#737)
Browse files Browse the repository at this point in the history
  • Loading branch information
nesadrian authored May 27, 2024
1 parent f0e6128 commit 89bea20
Show file tree
Hide file tree
Showing 19 changed files with 304 additions and 126 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

![image](https://github.com/equinor/flyt/assets/115637685/b2cbc217-1b39-4668-b891-afed82edcd01)


# Links

- 🌱 [Internal repo](https://github.com/equinor/flyt-internal)
Expand Down
33 changes: 23 additions & 10 deletions components/canvas/ChoiceNode.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useEffect, useState } from "react";
import { Connection, NodeProps, Position, useStore } from "reactflow";

import { NodeButtonsContainer } from "./NodeButtonsContainer";
import { SubActivityButton } from "./SubActivityButton";
import { ChoiceButton } from "./ChoiceButton";
Expand All @@ -13,7 +12,9 @@ import colors from "theme/colors";
import { NodeCard } from "./NodeCard";
import { NodeDescription } from "./NodeDescription";
import { SourceHandle } from "./SourceHandle";
import { formatNodeText } from "./utils/formatNodeText";
import { NodeShape } from "./NodeShape";
import { NodeTooltip } from "./NodeTooltip";
import { NodeTooltipSection } from "./NodeTooltipSection";

export const ChoiceNode = ({
data: {
Expand All @@ -37,11 +38,13 @@ export const ChoiceNode = ({
dragging,
}: NodeProps<NodeData>) => {
const [hovering, setHovering] = useState(false);
const [hoveringShape, setHoveringShape] = useState(false);
const connectionNodeId = useStore((state) => state.connectionNodeId);
const lastChild = children[children?.length - 1];

useEffect(() => {
setHovering(false);
setHoveringShape(false);
}, [dragging, connectionNodeId]);

const renderNodeButtons = () => {
Expand Down Expand Up @@ -137,22 +140,32 @@ export const ChoiceNode = ({
onMouseLeave={() => setHovering(false)}
>
<NodeCard
shape="rhombus"
height={shapeHeight}
width={shapeWidth}
color={colors.NODE_CHOICE}
onClick={handleClickNode}
hovering={hovering && !merging}
highlighted={isDropTarget && isValidDropTarget}
darkened={isValidDropTarget === false}
>
<NodeDescription
header={!description ? type : undefined}
description={description}
/>
<NodeShape
shape={"rhombus"}
color={colors.NODE_CHOICE}
width={shapeWidth}
height={shapeHeight}
onMouseEnter={() => !dragging && setHoveringShape(true)}
onMouseLeave={() => setHoveringShape(false)}
>
<NodeDescription
header={!description ? type : undefined}
description={description}
/>
</NodeShape>
</NodeCard>
<TargetHandle hidden={!mergeOption} />
<SourceHandle />
<NodeTooltip isVisible={!!(hoveringShape && description)}>
{description && (
<NodeTooltipSection header={"Description"} text={description} />
)}
</NodeTooltip>
{renderNodeButtons()}
</div>
);
Expand Down
34 changes: 27 additions & 7 deletions components/canvas/GenericNode.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NodeData } from "types/NodeData";
import { useState } from "react";
import { useState, useEffect } from "react";
import { Handle, NodeProps, Position } from "reactflow";
import stylesNodeButtons from "./NodeButtons.module.scss";
import { NodeButtonsContainer } from "./NodeButtonsContainer";
Expand All @@ -8,6 +8,10 @@ import { NodeTypes } from "types/NodeTypes";
import { NodeDescription } from "./NodeDescription";
import { NodeCard } from "./NodeCard";
import colors from "theme/colors";
import { QIPRContainer } from "./QIPRContainer";
import { NodeShape } from "./NodeShape";
import { NodeTooltip } from "./NodeTooltip";
import { NodeTooltipSection } from "./NodeTooltipSection";

export const GenericNode = ({
data: {
Expand All @@ -27,6 +31,12 @@ export const GenericNode = ({
dragging,
}: NodeProps<NodeData>) => {
const [hovering, setHovering] = useState(false);
const [hoveringShape, setHoveringShape] = useState(false);

useEffect(() => {
setHovering(false);
setHoveringShape(false);
}, [dragging]);

const renderNodeButtons = () => {
const nodeButtonsPosition =
Expand Down Expand Up @@ -58,24 +68,34 @@ export const GenericNode = ({
onMouseLeave={() => setHovering(false)}
>
<NodeCard
shape="square"
height={shapeHeight}
width={shapeWidth}
color={colors.NODE_GENERIC}
tasks={tasks}
onClick={handleClickNode}
hovering={hovering && !merging}
highlighted={isDropTarget && isValidDropTarget}
darkened={isValidDropTarget === false}
>
<NodeDescription header={type} description={description} />
<NodeShape
shape={"square"}
color={colors.NODE_GENERIC}
width={shapeWidth}
height={shapeHeight}
onMouseEnter={() => !dragging && setHoveringShape(true)}
onMouseLeave={() => setHoveringShape(false)}
>
<NodeDescription header={type} description={description} />
</NodeShape>
<QIPRContainer tasks={tasks} />
</NodeCard>
<Handle
className={stylesNodeButtons["handle--hidden"]}
type="target"
position={Position.Top}
isConnectable={false}
/>
<NodeTooltip isVisible={!!(hoveringShape && description)}>
{description && (
<NodeTooltipSection header={"Description"} text={description} />
)}
</NodeTooltip>
{renderNodeButtons()}
</div>
);
Expand Down
34 changes: 25 additions & 9 deletions components/canvas/MainActivityNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import { NodeDescription } from "./NodeDescription";
import { NodeCard } from "./NodeCard";
import colors from "theme/colors";
import { SourceHandle } from "./SourceHandle";
import { NodeShape } from "./NodeShape";
import { QIPRContainer } from "./QIPRContainer";
import { NodeTooltipSection } from "./NodeTooltipSection";
import { NodeTooltip } from "./NodeTooltip";

export const MainActivityNode = ({
data: {
Expand All @@ -32,9 +36,11 @@ export const MainActivityNode = ({
dragging,
}: NodeProps<NodeData>) => {
const [hovering, setHovering] = useState(false);
const [hoveringShape, setHoveringShape] = useState(false);

useEffect(() => {
setHovering(false);
setHoveringShape(false);
}, [dragging]);

const renderNodeButtons = () => {
Expand Down Expand Up @@ -82,20 +88,25 @@ export const MainActivityNode = ({
onMouseLeave={() => setHovering(false)}
>
<NodeCard
shape="square"
height={shapeHeight}
width={shapeWidth}
color={colors.NODE_MAINACTIVITY}
tasks={tasks}
onClick={handleClickNode}
hovering={hovering && !merging}
highlighted={isDropTarget && isValidDropTarget}
darkened={isValidDropTarget === false}
>
<NodeDescription
header={!description ? type : undefined}
description={description}
/>
<NodeShape
shape={"square"}
color={colors.NODE_MAINACTIVITY}
width={shapeWidth}
height={shapeHeight}
onMouseEnter={() => !dragging && setHoveringShape(true)}
onMouseLeave={() => setHoveringShape(false)}
>
<NodeDescription
header={!description ? type : undefined}
description={description}
/>
</NodeShape>
<QIPRContainer tasks={tasks} />
</NodeCard>
<Handle
className={stylesNodeButtons["handle--hidden"]}
Expand All @@ -104,6 +115,11 @@ export const MainActivityNode = ({
isConnectable={false}
/>
<SourceHandle />
<NodeTooltip isVisible={!!(hoveringShape && description)}>
{description && (
<NodeTooltipSection header={"Description"} text={description} />
)}
</NodeTooltip>
{renderNodeButtons()}
</div>
);
Expand Down
18 changes: 1 addition & 17 deletions components/canvas/NodeCard.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import { Task } from "types/Task";
import styles from "./Node.module.scss";
import { QIPRContainer } from "./QIPRContainer";
import { NodeShape } from "./NodeShape";

type NodeCard = {
shape: "square" | "rhombus";
color: string;
height: number;
width: number;
tasks?: Task[];
onClick: () => void;
hovering?: boolean;
highlighted?: boolean;
Expand All @@ -17,11 +9,6 @@ type NodeCard = {
};

export const NodeCard = ({
shape,
height,
width,
color,
tasks,
onClick,
hovering,
highlighted,
Expand All @@ -38,9 +25,6 @@ export const NodeCard = ({
}`}
onClick={onClick}
>
<NodeShape shape={shape} color={color} width={width} height={height}>
{children}
</NodeShape>
<QIPRContainer tasks={tasks} />
{children}
</div>
);
30 changes: 16 additions & 14 deletions components/canvas/NodeDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ type NodeDescription = {
description?: string;
};

export const NodeDescription = ({ header, description }: NodeDescription) => (
<div className={styles["node__description-container"]}>
{header && (
<Typography variant="caption" className={styles["node__header"]}>
{getNodeTypeName(header)}
</Typography>
)}
{description && (
<Typography variant="caption" className={styles["node__description"]}>
{formatNodeText(description)}
</Typography>
)}
</div>
);
export const NodeDescription = ({ header, description }: NodeDescription) => {
return (
<div className={styles["node__description-container"]}>
{header && (
<Typography variant="caption" className={styles["node__header"]}>
{getNodeTypeName(header)}
</Typography>
)}
{description && (
<Typography variant="caption" className={styles["node__description"]}>
{formatNodeText(description)}
</Typography>
)}
</div>
);
};
9 changes: 9 additions & 0 deletions components/canvas/NodeShape.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { MouseEventHandler } from "react";
import styles from "./Node.module.scss";

type NodeShape = {
Expand All @@ -6,6 +7,8 @@ type NodeShape = {
width: number;
height: number;
children: JSX.Element | JSX.Element[];
onMouseEnter?: MouseEventHandler<HTMLDivElement>;
onMouseLeave?: MouseEventHandler<HTMLDivElement>;
};

export const NodeShape = ({
Expand All @@ -14,11 +17,15 @@ export const NodeShape = ({
width,
height,
children,
onMouseEnter,
onMouseLeave,
}: NodeShape) => {
const square = (
<div
style={{ height: height, width: width }}
className={`${styles["node-shape-container"]} ${styles["node-shape-container--square"]}`}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<div
className={`${styles["node-shape--square"]}`}
Expand All @@ -33,6 +40,8 @@ export const NodeShape = ({
<div
style={{ height: height, width: width }}
className={styles["node-shape-container"]}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<div
className={`${styles["node-shape--rhombus"]} `}
Expand Down
12 changes: 12 additions & 0 deletions components/canvas/NodeTooltip.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@import "styles/_variables.scss";

.container {
background: white;
max-width: 300px;
box-shadow: 0px 11px 15px 0px #00000033;
border-radius: 2.5%;
}

.container > * + * {
border-top: 1px solid $equinor_MEDIUM_GRAY;
}
21 changes: 21 additions & 0 deletions components/canvas/NodeTooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ReactNode } from "react";
import { NodeToolbar, Position } from "reactflow";
import styles from "./NodeTooltip.module.scss";

type NodeTooltip = {
children: ReactNode;
isVisible?: boolean;
position?: Position;
};

export const NodeTooltip = ({ children, isVisible, position }: NodeTooltip) => {
return (
<NodeToolbar
position={position}
isVisible={isVisible}
className={styles.container}
>
{children}
</NodeToolbar>
);
};
6 changes: 6 additions & 0 deletions components/canvas/NodeTooltipSection.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.container {
padding: 10px 20px;
overflow: hidden;
white-space: pre-wrap;
overflow-wrap: break-word;
}
17 changes: 17 additions & 0 deletions components/canvas/NodeTooltipSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Typography } from "@equinor/eds-core-react";
import styles from "./NodeTooltipSection.module.scss";
import { formatNodeText } from "./utils/formatNodeText";

type NodeTooltipSection = {
header?: string;
text: string;
};

export const NodeTooltipSection = ({ header, text }: NodeTooltipSection) => (
<div className={styles.container}>
<Typography variant="meta" color="Gray">
{formatNodeText(header)}
</Typography>
<Typography variant="body_long">{formatNodeText(text)}</Typography>
</div>
);
Loading

0 comments on commit 89bea20

Please sign in to comment.