Skip to content

Commit 628c998

Browse files
authored
Merge pull request #62 from NGO-Algorithm-Audit/feature/tooltip-tweaks
Feature/tooltip tweaks
2 parents 1f8d714 + cfaeec0 commit 628c998

File tree

3 files changed

+80
-69
lines changed

3 files changed

+80
-69
lines changed

src/components/TooltipWrapper.tsx

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { InfoIcon } from 'lucide-react';
21
import {
32
Tooltip,
43
TooltipContent,
@@ -9,30 +8,26 @@ import { MarkdownWithTooltips } from './MarkdownWithTooltips';
98

109
interface TooltipWrapperProps {
1110
tooltipContent: string;
11+
children: React.ReactNode;
1212
textBefore?: string;
1313
textAfter?: string;
14-
children: React.ReactNode;
1514
}
1615

1716
export function TooltipWrapper({
1817
tooltipContent,
18+
children,
1919
textBefore,
2020
textAfter,
21-
children,
2221
}: TooltipWrapperProps) {
2322
return (
24-
<div>
23+
<span>
2524
{textBefore}
26-
{children}
27-
2825
<TooltipProvider>
2926
<Tooltip>
30-
<TooltipTrigger
31-
onClick={event => {
32-
event.preventDefault();
33-
}}
34-
>
35-
<InfoIcon className="size-3.5 ml-1" />
27+
<TooltipTrigger asChild>
28+
<span className="border-b-2 border-dashed border-gray-600 cursor-help">
29+
{children}
30+
</span>
3631
</TooltipTrigger>
3732
<TooltipContent className="tooltip-content max-w-[400px] p-2">
3833
<MarkdownWithTooltips className="text-gray-800 markdown">
@@ -42,6 +37,6 @@ export function TooltipWrapper({
4237
</Tooltip>
4338
</TooltipProvider>
4439
{textAfter}
45-
</div>
40+
</span>
4641
);
4742
}

src/components/remark-info-tooltip.tsx

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ interface ParentNode extends Node {
1414
interface CustomElementData extends ElementData {
1515
hProperties?: {
1616
tooltip?: string;
17+
textBefore?: string;
18+
textAfter?: string;
1719
};
1820
}
1921

@@ -28,59 +30,77 @@ export function remarkInfoTooltip() {
2830
);
2931

3032
if (matches) {
33+
let lastIndex = 0;
34+
const newChildren: Node[] = [];
35+
3136
matches.forEach(match => {
3237
const tooltipMatch = match.match(
3338
/\{tooltip:([^}]+)\}(.*?)\{\/tooltip\}/
3439
);
3540
if (tooltipMatch) {
3641
const [, tooltipContent, text] = tooltipMatch;
37-
const index = node.value.indexOf(match);
38-
if (index !== -1) {
39-
// Create a new element node
40-
const elementNode: Element = {
41-
type: 'element',
42-
tagName: 'div',
43-
properties: {
42+
const index = node.value.indexOf(match, lastIndex);
43+
44+
// Add text before the tooltip
45+
const textBefore = node.value.slice(
46+
lastIndex,
47+
index
48+
);
49+
if (textBefore) {
50+
const textNode: TextNode = {
51+
type: 'text',
52+
value: textBefore,
53+
};
54+
newChildren.push(textNode);
55+
}
56+
57+
// Create a new element node for the tooltip
58+
const elementNode: Element = {
59+
type: 'element',
60+
tagName: 'span',
61+
properties: {
62+
tooltip: tooltipContent,
63+
},
64+
data: {
65+
hProperties: {
4466
tooltip: tooltipContent,
45-
// textBefore: node.value.slice(0, index),
46-
// textAfter: node.value.slice(
47-
// index + match.length
48-
// ),
4967
},
50-
data: {
51-
hProperties: {
52-
tooltip: tooltipContent,
53-
textBefore: node.value.slice(
54-
0,
55-
index
56-
),
57-
textAfter: node.value.slice(
58-
index + match.length
59-
),
60-
},
61-
} as CustomElementData,
62-
children: [
63-
{
64-
type: 'text',
65-
value: text,
66-
},
67-
],
68-
};
68+
} as CustomElementData,
69+
children: [
70+
{
71+
type: 'text',
72+
value: text,
73+
} as TextNode,
74+
],
75+
};
76+
newChildren.push(elementNode);
6977

70-
// Replace the text node with the element node
71-
if (ancestors.length > 0) {
72-
const parent =
73-
ancestors[ancestors.length - 1];
74-
const nodeIndex =
75-
parent.children.indexOf(node);
76-
if (nodeIndex !== -1) {
77-
parent.children[nodeIndex] =
78-
elementNode;
79-
}
80-
}
81-
}
78+
lastIndex = index + match.length;
8279
}
8380
});
81+
82+
// Add any remaining text after the last tooltip
83+
const remainingText = node.value.slice(lastIndex);
84+
if (remainingText) {
85+
const textNode: TextNode = {
86+
type: 'text',
87+
value: remainingText,
88+
};
89+
newChildren.push(textNode);
90+
}
91+
92+
// Replace the text node with the new children
93+
if (ancestors.length > 0) {
94+
const parent = ancestors[ancestors.length - 1];
95+
const nodeIndex = parent.children.indexOf(node);
96+
if (nodeIndex !== -1) {
97+
parent.children.splice(
98+
nodeIndex,
99+
1,
100+
...newChildren
101+
);
102+
}
103+
}
84104
}
85105
}
86106
);

src/locales/en.ts

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -159,27 +159,23 @@ export const en = {
159159
'The figures below display the differences in value frequency for a combination of variables. For comparing two categorical variables, bar charts are plotted. For comparing a numerical and a categorical variables, a so called [violin plot](https://en.wikipedia.org/wiki/Violin_plot) is shown. For comparing two numercial variables, a [LOESS plot](https://en.wikipedia.org/wiki/Local_regression) is created. For all plots holds: the synthetic data is of high quality when the shape of the distributions in the synthetic data equal the distributions in the real data.',
160160
moreInfo:
161161
'Do you want to learn more about synthetic data?\n \n \n \n- [python-synthpop on Github](https://github.com/NGO-Algorithm-Audit/python-synthpop)\n- [local-first web app on Github](https://github.com/NGO-Algorithm-Audit/local-first-web-tool/tree/main)\n- [Synthetic Data: what, why and how?](https://royalsociety.org/-/media/policy/projects/privacy-enhancing-technologies/Synthetic_Data_Survey-24.pdf)\n- [Knowledge Network Synthetic Data](https://online.rijksinnovatiecommunity.nl/groups/399-kennisnetwerk-synthetischedata/welcome) (for Dutch public organizations)\n- [Synthetic data portal of Dutch Executive Agency for Education](https://duo.nl/open_onderwijsdata/footer/synthetische-data.jsp) (DUO)\n- [CART: synthpop resources](https://synthpop.org.uk/resources.html)\n- [Gaussian Copula - Synthetic Data Vault](https://docs.sdv.dev/sdv)',
162-
missingData: `For Missing At Random (MAR) and Missing Not At Random (MNAR) data,
163-
we recommend to impute the missing data. For Missing Completely At Random (MCAR), we recommend to remove the missing data. {tooltip:syntheticData.missingDataTooltip}See the info box for more information{/tooltip}.`,
164-
missingDataTooltip: `MCAR, MAR, and MNAR are terms used to describe different mechanisms of missing data:
165-
166-
1. **MCAR (Missing Completely At Random)**:
167-
- The probability of data being missing is completely independent of both observed and unobserved data.
168-
- There is no systematic pattern to the missingness.
169-
- Example: A survey respondent accidentally skips a question due to a printing error.
170-
- Recommendation: remove missing data.
171-
172-
2. **MAR (Missing At Random)**:
162+
missingData: `For {tooltip:syntheticData.missingDataMARTooltip}Missing At Random (MAR){/tooltip} and {tooltip:syntheticData.missingDataMNARTooltip}Missing Not At Random (MNAR){/tooltip} data,
163+
we recommend to impute the missing data. For {tooltip:syntheticData.missingDataMCARTooltip}Missing Completely At Random (MCAR){/tooltip}, we recommend to remove the missing data.`,
164+
missingDataMARTooltip: `**MAR (Missing At Random)**:
173165
- The probability of data being missing is related to the observed data but not the missing data itself.
174166
- The missingness can be predicted by other variables in the dataset.
175167
- Example: Students' test scores are missing, but the missingness is related to their attendance records.
176-
- Recommendation: impute missing data.
177-
178-
3. **MNAR (Missing Not At Random)**:
168+
- Recommendation: impute missing data.`,
169+
missingDataMNARTooltip: `**MNAR (Missing Not At Random)**:
179170
- The probability of data being missing is related to the missing data itself.
180171
- There is a systematic pattern to the missingness that is related to the unobserved data.
181172
- Example: Patients with more severe symptoms are less likely to report their symptoms, leading to missing data that is related to the severity of the symptoms.
182173
- Recommendation: impute missing data.`,
174+
missingDataMCARTooltip: `**MCAR (Missing Completely At Random)**:
175+
- The probability of data being missing is completely independent of both observed and unobserved data.
176+
- There is no systematic pattern to the missingness.
177+
- Example: A survey respondent accidentally skips a question due to a printing error.
178+
- Recommendation: remove missing data.`,
183179
},
184180

185181
biasAnalysis: {

0 commit comments

Comments
 (0)