darabos commited on
Commit
d7943fc
·
1 Parent(s): 3006c30

Use React Tooltip.

Browse files
lynxkite-app/web/package-lock.json CHANGED
@@ -30,6 +30,7 @@
30
  "react-error-boundary": "^5.0.0",
31
  "react-markdown": "^9.0.1",
32
  "react-router-dom": "^7.5.2",
 
33
  "swr": "^2.2.5",
34
  "unplugin-icons": "^0.21.0",
35
  "y-monaco": "^0.1.6",
@@ -940,6 +941,31 @@
940
  "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
941
  }
942
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
943
  "node_modules/@humanfs/core": {
944
  "version": "0.19.1",
945
  "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -2879,6 +2905,12 @@
2879
  "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==",
2880
  "license": "MIT"
2881
  },
 
 
 
 
 
 
2882
  "node_modules/client-only": {
2883
  "version": "0.0.1",
2884
  "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
@@ -6239,6 +6271,20 @@
6239
  "react-dom": ">=18"
6240
  }
6241
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6242
  "node_modules/read-cache": {
6243
  "version": "1.0.0",
6244
  "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
 
30
  "react-error-boundary": "^5.0.0",
31
  "react-markdown": "^9.0.1",
32
  "react-router-dom": "^7.5.2",
33
+ "react-tooltip": "^5.28.1",
34
  "swr": "^2.2.5",
35
  "unplugin-icons": "^0.21.0",
36
  "y-monaco": "^0.1.6",
 
941
  "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
942
  }
943
  },
944
+ "node_modules/@floating-ui/core": {
945
+ "version": "1.6.9",
946
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz",
947
+ "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==",
948
+ "license": "MIT",
949
+ "dependencies": {
950
+ "@floating-ui/utils": "^0.2.9"
951
+ }
952
+ },
953
+ "node_modules/@floating-ui/dom": {
954
+ "version": "1.6.13",
955
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz",
956
+ "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==",
957
+ "license": "MIT",
958
+ "dependencies": {
959
+ "@floating-ui/core": "^1.6.0",
960
+ "@floating-ui/utils": "^0.2.9"
961
+ }
962
+ },
963
+ "node_modules/@floating-ui/utils": {
964
+ "version": "0.2.9",
965
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
966
+ "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
967
+ "license": "MIT"
968
+ },
969
  "node_modules/@humanfs/core": {
970
  "version": "0.19.1",
971
  "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
 
2905
  "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==",
2906
  "license": "MIT"
2907
  },
2908
+ "node_modules/classnames": {
2909
+ "version": "2.5.1",
2910
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
2911
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
2912
+ "license": "MIT"
2913
+ },
2914
  "node_modules/client-only": {
2915
  "version": "0.0.1",
2916
  "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
 
6271
  "react-dom": ">=18"
6272
  }
6273
  },
6274
+ "node_modules/react-tooltip": {
6275
+ "version": "5.28.1",
6276
+ "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.28.1.tgz",
6277
+ "integrity": "sha512-ZA4oHwoIIK09TS7PvSLFcRlje1wGZaxw6xHvfrzn6T82UcMEfEmHVCad16Gnr4NDNDh93HyN037VK4HDi5odfQ==",
6278
+ "license": "MIT",
6279
+ "dependencies": {
6280
+ "@floating-ui/dom": "^1.6.1",
6281
+ "classnames": "^2.3.0"
6282
+ },
6283
+ "peerDependencies": {
6284
+ "react": ">=16.14.0",
6285
+ "react-dom": ">=16.14.0"
6286
+ }
6287
+ },
6288
  "node_modules/read-cache": {
6289
  "version": "1.0.0",
6290
  "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
lynxkite-app/web/package.json CHANGED
@@ -33,6 +33,7 @@
33
  "react-error-boundary": "^5.0.0",
34
  "react-markdown": "^9.0.1",
35
  "react-router-dom": "^7.5.2",
 
36
  "swr": "^2.2.5",
37
  "unplugin-icons": "^0.21.0",
38
  "y-monaco": "^0.1.6",
 
33
  "react-error-boundary": "^5.0.0",
34
  "react-markdown": "^9.0.1",
35
  "react-router-dom": "^7.5.2",
36
+ "react-tooltip": "^5.28.1",
37
  "swr": "^2.2.5",
38
  "unplugin-icons": "^0.21.0",
39
  "y-monaco": "^0.1.6",
lynxkite-app/web/src/{workspace/nodes/NodeDocumentation.tsx → Tooltip.tsx} RENAMED
@@ -1,16 +1,21 @@
 
1
  import Markdown from "react-markdown";
 
2
 
3
- export default function NodeDocumentation(props: any) {
 
4
  if (!props.doc) return null;
5
  return (
6
- <div className="dropdown dropdown-hover dropdown-top dropdown-end title-icon">
7
- {props.children}
8
- <div className="node-documentation dropdown-content" style={{ width: props.width }}>
 
 
9
  {props.doc.map?.(
10
  (section: any, i: number) =>
11
  section.kind === "text" && <Markdown key={i}>{section.value}</Markdown>,
12
  ) ?? <Markdown>{props.doc}</Markdown>}
13
- </div>
14
- </div>
15
  );
16
  }
 
1
+ import { useId } from "react";
2
  import Markdown from "react-markdown";
3
+ import { Tooltip as ReactTooltip } from "react-tooltip";
4
 
5
+ export default function Tooltip(props: any) {
6
+ const id = useId();
7
  if (!props.doc) return null;
8
  return (
9
+ <>
10
+ <a data-tooltip-id={id} tabIndex={0}>
11
+ {props.children}
12
+ </a>
13
+ <ReactTooltip id={id} className="tooltip" place="top-end">
14
  {props.doc.map?.(
15
  (section: any, i: number) =>
16
  section.kind === "text" && <Markdown key={i}>{section.value}</Markdown>,
17
  ) ?? <Markdown>{props.doc}</Markdown>}
18
+ </ReactTooltip>
19
+ </>
20
  );
21
  }
lynxkite-app/web/src/index.css CHANGED
@@ -68,11 +68,6 @@ body {
68
  font-size: 12px;
69
  }
70
 
71
- .title-icon {
72
- margin-left: 5px;
73
- float: right;
74
- }
75
-
76
  .node-container {
77
  padding: 8px;
78
  position: relative;
@@ -91,16 +86,20 @@ body {
91
  display: flex;
92
  flex-direction: column;
93
  }
 
94
 
95
- .node-documentation {
96
- padding: 8px;
97
- border-radius: 4px;
98
- background: #fffa;
99
- box-shadow: 0px 5px 50px 0px rgba(0, 0, 0, 0.1);
100
- backdrop-filter: blur(10px);
101
- font-size: 12px;
102
- font-weight: initial;
103
- }
 
 
 
104
  }
105
 
106
  .expanded .lynxkite-node {
@@ -123,6 +122,13 @@ body {
123
  --status-color-2: #0000;
124
  --status-color-3: #0000;
125
  transition: --status-color-1 0.3s, --status-color-2 0.3s, --status-color-3 0.3s;
 
 
 
 
 
 
 
126
  }
127
 
128
  .lynxkite-node .title.active {
 
68
  font-size: 12px;
69
  }
70
 
 
 
 
 
 
71
  .node-container {
72
  padding: 8px;
73
  position: relative;
 
86
  display: flex;
87
  flex-direction: column;
88
  }
89
+ }
90
 
91
+ .tooltip {
92
+ padding: 8px;
93
+ border-radius: 4px;
94
+ opacity: 1;
95
+ text-align: left;
96
+ background: #fffa;
97
+ color: black;
98
+ box-shadow: 0px 5px 50px 0px rgba(0, 0, 0, 0.1);
99
+ backdrop-filter: blur(10px);
100
+ font-size: 16px;
101
+ font-weight: initial;
102
+ max-width: 300px;
103
  }
104
 
105
  .expanded .lynxkite-node {
 
122
  --status-color-2: #0000;
123
  --status-color-3: #0000;
124
  transition: --status-color-1 0.3s, --status-color-2 0.3s, --status-color-3 0.3s;
125
+ display: flex;
126
+ flex-direction: row;
127
+ gap: 10px;
128
+
129
+ .title-title {
130
+ flex: 1;
131
+ }
132
  }
133
 
134
  .lynxkite-node .title.active {
lynxkite-app/web/src/workspace/nodes/LynxKiteNode.tsx CHANGED
@@ -11,7 +11,7 @@ import Dots from "~icons/tabler/dots.jsx";
11
  import Help from "~icons/tabler/question-mark.jsx";
12
  // @ts-ignore
13
  import Skull from "~icons/tabler/skull.jsx";
14
- import NodeDocumentation from "./NodeDocumentation";
15
 
16
  interface LynxKiteNodeProps {
17
  id: string;
@@ -91,22 +91,20 @@ function LynxKiteNodeComponent(props: LynxKiteNodeProps) {
91
  style={titleStyle}
92
  onClick={titleClicked}
93
  >
94
- {data.title}
95
  {data.error && (
96
- <span className="title-icon">
97
  <AlertTriangle />
98
- </span>
99
  )}
100
  {expanded || (
101
- <span className="title-icon">
102
  <Dots />
103
- </span>
104
  )}
105
- <NodeDocumentation doc={data.meta?.value?.doc} width={props.width - 60}>
106
- <button tabIndex={0}>
107
- <Help />
108
- </button>
109
- </NodeDocumentation>
110
  </div>
111
  {expanded && (
112
  <>
 
11
  import Help from "~icons/tabler/question-mark.jsx";
12
  // @ts-ignore
13
  import Skull from "~icons/tabler/skull.jsx";
14
+ import Tooltip from "../../Tooltip";
15
 
16
  interface LynxKiteNodeProps {
17
  id: string;
 
91
  style={titleStyle}
92
  onClick={titleClicked}
93
  >
94
+ <span className="title-title">{data.title}</span>
95
  {data.error && (
96
+ <Tooltip doc={`Error: ${data.error}`}>
97
  <AlertTriangle />
98
+ </Tooltip>
99
  )}
100
  {expanded || (
101
+ <Tooltip doc="Click to expand node">
102
  <Dots />
103
+ </Tooltip>
104
  )}
105
+ <Tooltip doc={data.meta?.value?.doc}>
106
+ <Help />
107
+ </Tooltip>
 
 
108
  </div>
109
  {expanded && (
110
  <>
lynxkite-app/web/src/workspace/nodes/NodeParameter.tsx CHANGED
@@ -3,7 +3,7 @@ import { useRef } from "react";
3
  import ArrowsHorizontal from "~icons/tabler/arrows-horizontal.jsx";
4
  // @ts-ignore
5
  import Help from "~icons/tabler/question-mark.jsx";
6
- import NodeDocumentation from "./NodeDocumentation";
7
  import NodeGroupParameter from "./NodeGroupParameter";
8
 
9
  const BOOLEAN = "<class 'bool'>";
@@ -15,11 +15,9 @@ const MODEL_OUTPUT_MAPPING = "<class 'lynxkite_graph_analytics.ml_ops.ModelOutpu
15
 
16
  function ParamName({ name, doc }: { name: string; doc: string }) {
17
  const help = doc && (
18
- <NodeDocumentation doc={doc} width={200}>
19
- <button tabIndex={0}>
20
- <Help />
21
- </button>
22
- </NodeDocumentation>
23
  );
24
  return (
25
  <div className="param-name-row">
@@ -230,12 +228,12 @@ export default function NodeParameter({ name, value, meta, data, setParam }: Nod
230
  }
231
  return meta?.type?.format === "collapsed" ? (
232
  <label className="param">
233
- <ParamName name={name} />
234
  <button className="collapsed-param">⋯</button>
235
  </label>
236
  ) : meta?.type?.format === "textarea" ? (
237
  <label className="param">
238
- <ParamName name={name} />
239
  <textarea
240
  className="textarea textarea-bordered w-full"
241
  rows={6}
@@ -248,7 +246,7 @@ export default function NodeParameter({ name, value, meta, data, setParam }: Nod
248
  <NodeGroupParameter meta={meta} data={data} setParam={setParam} />
249
  ) : meta?.type?.enum ? (
250
  <label className="param">
251
- <ParamName name={name} />
252
  <select
253
  className="select select-bordered w-full"
254
  value={value || meta.type.enum[0]}
@@ -275,17 +273,17 @@ export default function NodeParameter({ name, value, meta, data, setParam }: Nod
275
  </div>
276
  ) : meta?.type?.type === MODEL_TRAINING_INPUT_MAPPING ? (
277
  <label className="param">
278
- <ParamName name={name} />
279
  <ModelMapping value={value} data={data} variant="training input" onChange={onChange} />
280
  </label>
281
  ) : meta?.type?.type === MODEL_INFERENCE_INPUT_MAPPING ? (
282
  <label className="param">
283
- <ParamName name={name} />
284
  <ModelMapping value={value} data={data} variant="inference input" onChange={onChange} />
285
  </label>
286
  ) : meta?.type?.type === MODEL_OUTPUT_MAPPING ? (
287
  <label className="param">
288
- <ParamName name={name} />
289
  <ModelMapping value={value} data={data} variant="output" onChange={onChange} />
290
  </label>
291
  ) : (
 
3
  import ArrowsHorizontal from "~icons/tabler/arrows-horizontal.jsx";
4
  // @ts-ignore
5
  import Help from "~icons/tabler/question-mark.jsx";
6
+ import Tooltip from "../../Tooltip";
7
  import NodeGroupParameter from "./NodeGroupParameter";
8
 
9
  const BOOLEAN = "<class 'bool'>";
 
15
 
16
  function ParamName({ name, doc }: { name: string; doc: string }) {
17
  const help = doc && (
18
+ <Tooltip doc={doc} width={200}>
19
+ <Help />
20
+ </Tooltip>
 
 
21
  );
22
  return (
23
  <div className="param-name-row">
 
228
  }
229
  return meta?.type?.format === "collapsed" ? (
230
  <label className="param">
231
+ <ParamName name={name} doc={doc} />
232
  <button className="collapsed-param">⋯</button>
233
  </label>
234
  ) : meta?.type?.format === "textarea" ? (
235
  <label className="param">
236
+ <ParamName name={name} doc={doc} />
237
  <textarea
238
  className="textarea textarea-bordered w-full"
239
  rows={6}
 
246
  <NodeGroupParameter meta={meta} data={data} setParam={setParam} />
247
  ) : meta?.type?.enum ? (
248
  <label className="param">
249
+ <ParamName name={name} doc={doc} />
250
  <select
251
  className="select select-bordered w-full"
252
  value={value || meta.type.enum[0]}
 
273
  </div>
274
  ) : meta?.type?.type === MODEL_TRAINING_INPUT_MAPPING ? (
275
  <label className="param">
276
+ <ParamName name={name} doc={doc} />
277
  <ModelMapping value={value} data={data} variant="training input" onChange={onChange} />
278
  </label>
279
  ) : meta?.type?.type === MODEL_INFERENCE_INPUT_MAPPING ? (
280
  <label className="param">
281
+ <ParamName name={name} doc={doc} />
282
  <ModelMapping value={value} data={data} variant="inference input" onChange={onChange} />
283
  </label>
284
  ) : meta?.type?.type === MODEL_OUTPUT_MAPPING ? (
285
  <label className="param">
286
+ <ParamName name={name} doc={doc} />
287
  <ModelMapping value={value} data={data} variant="output" onChange={onChange} />
288
  </label>
289
  ) : (