Added HoverTooltip component. Removed react-tooltip.

This commit is contained in:
Mike Cao 2023-03-14 11:35:24 -07:00
parent 9a3e8921a7
commit 3823705fc6
9 changed files with 56 additions and 75 deletions

View File

@ -0,0 +1,25 @@
import { useEffect, useState } from 'react';
import { Tooltip } from 'react-basics';
import styles from './HoverTooltip.module.css';
export default function HoverTooltip({ tooltip }) {
const [position, setPosition] = useState({ x: -1000, y: -1000 });
useEffect(() => {
const handler = e => {
setPosition({ x: e.clientX, y: e.clientY });
};
document.addEventListener('mousemove', handler);
return () => {
document.removeEventListener('mousemove', handler);
};
}, []);
return (
<div className={styles.tooltip} style={{ left: position.x, top: position.y }}>
<Tooltip position="top" action="none" label={tooltip} />
</div>
);
}

View File

@ -3,7 +3,7 @@
} }
.tooltip { .tooltip {
color: var(--msgColor); position: fixed;
pointer-events: none; pointer-events: none;
z-index: 1; z-index: 1;
} }

View File

@ -1,6 +1,5 @@
import { useState, useMemo } from 'react'; import { useState, useMemo } from 'react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import ReactTooltip from 'react-tooltip';
import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps'; import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps';
import classNames from 'classnames'; import classNames from 'classnames';
import { colord } from 'colord'; import { colord } from 'colord';
@ -9,6 +8,8 @@ import { ISO_COUNTRIES, THEME_COLORS, MAP_FILE } from 'lib/constants';
import styles from './WorldMap.module.css'; import styles from './WorldMap.module.css';
import useCountryNames from 'hooks/useCountryNames'; import useCountryNames from 'hooks/useCountryNames';
import useLocale from 'hooks/useLocale'; import useLocale from 'hooks/useLocale';
import HoverTooltip from './HoverTooltip';
import { formatLongNumber } from '../../lib/format';
function WorldMap({ data, className }) { function WorldMap({ data, className }) {
const { basePath } = useRouter(); const { basePath } = useRouter();
@ -46,7 +47,7 @@ function WorldMap({ data, className }) {
function handleHover(code) { function handleHover(code) {
if (code === 'AQ') return; if (code === 'AQ') return;
const country = data?.find(({ x }) => x === code); const country = data?.find(({ x }) => x === code);
setTooltip(`${countryNames[code]}: ${country?.y || 0} visitors`); setTooltip(`${countryNames[code]}: ${formatLongNumber(country?.y || 0)} visitors`);
} }
return ( return (
@ -83,7 +84,7 @@ function WorldMap({ data, className }) {
</Geographies> </Geographies>
</ZoomableGroup> </ZoomableGroup>
</ComposableMap> </ComposableMap>
<ReactTooltip id="world-map-tooltip">{tooltip}</ReactTooltip> {tooltip && <HoverTooltip tooltip={tooltip} />}
</div> </div>
); );
} }

View File

@ -1,6 +1,8 @@
import { useState, useRef, useEffect } from 'react'; import { useState, useRef, useEffect } from 'react';
import { StatusLight } from 'react-basics';
import classNames from 'classnames'; import classNames from 'classnames';
import ChartJS from 'chart.js'; import ChartJS from 'chart.js';
import HoverTooltip from 'components/common/HoverTooltip';
import Legend from 'components/metrics/Legend'; import Legend from 'components/metrics/Legend';
import { formatLongNumber } from 'lib/format'; import { formatLongNumber } from 'lib/format';
import { dateFormat } from 'lib/date'; import { dateFormat } from 'lib/date';
@ -9,10 +11,8 @@ import useTheme from 'hooks/useTheme';
import useForceUpdate from 'hooks/useForceUpdate'; import useForceUpdate from 'hooks/useForceUpdate';
import { DEFAULT_ANIMATION_DURATION, THEME_COLORS } from 'lib/constants'; import { DEFAULT_ANIMATION_DURATION, THEME_COLORS } from 'lib/constants';
import styles from './BarChart.module.css'; import styles from './BarChart.module.css';
import ChartTooltip from './ChartTooltip';
export default function BarChart({ export default function BarChart({
chartId,
datasets, datasets,
unit, unit,
records, records,
@ -89,22 +89,20 @@ export default function BarChart({
} }
const [label, value] = body[0].lines[0].split(':'); const [label, value] = body[0].lines[0].split(':');
const format = unit === 'hour' ? 'EEE p — PPP' : 'PPPP';
setTooltip({ setTooltip(
title: dateFormat(new Date(+title[0]), getTooltipFormat(unit), locale), <>
value, <div>{dateFormat(new Date(+title[0]), format, locale)}</div>
label, <div>
labelColor: labelColors[0].backgroundColor, <StatusLight color={labelColors[0].backgroundColor}>
}); <b>
} {formatLongNumber(value)} {label}
</b>
function getTooltipFormat(unit) { </StatusLight>
switch (unit) { </div>
case 'hour': </>,
return 'EEE p — PPP'; );
default:
return 'PPPP';
}
} }
function createChart() { function createChart() {
@ -125,6 +123,9 @@ export default function BarChart({
legend: { legend: {
display: false, display: false,
}, },
onResize: ({ width, height }) => {
//console.log({ width, height });
},
scales: { scales: {
xAxes: [ xAxes: [
{ {
@ -206,19 +207,15 @@ export default function BarChart({
updateChart(); updateChart();
} }
} }
}, [datasets, unit, animationDuration, locale, theme]); }, [datasets, unit, animationDuration, locale]);
return ( return (
<> <>
<div <div className={classNames(styles.chart, className)}>
data-tip=""
data-for={`${chartId}-tooltip`}
className={classNames(styles.chart, className)}
>
<canvas ref={canvas} /> <canvas ref={canvas} />
</div> </div>
<Legend chart={chart.current} /> <Legend chart={chart.current} />
<ChartTooltip chartId={chartId} tooltip={tooltip} /> {tooltip && <HoverTooltip tooltip={tooltip} />}
</> </>
); );
} }

View File

@ -1,26 +0,0 @@
import { StatusLight } from 'react-basics';
import styles from './ChartTooltip.module.css';
import ReactTooltip from 'react-tooltip';
export default function ChartTooltip({ chartId, tooltip }) {
if (!tooltip) {
return null;
}
const { title, value, label, labelColor } = tooltip;
return (
<ReactTooltip id={`${chartId}-tooltip`}>
<div className={styles.tooltip}>
<div className={styles.content}>
<div className={styles.title}>{title}</div>
<div className={styles.metric}>
<StatusLight color={labelColor}>
{value} {label}
</StatusLight>
</div>
</div>
</div>
</ReactTooltip>
);
}

View File

@ -76,7 +76,6 @@ export default function EventsChart({ websiteId, className, token }) {
return ( return (
<BarChart <BarChart
chartId={`events-${websiteId}`}
className={className} className={className}
datasets={datasets} datasets={datasets}
unit={unit} unit={unit}

View File

@ -55,7 +55,6 @@ export default function PageviewsChart({
<BarChart <BarChart
{...props} {...props}
className={className} className={className}
chartId={websiteId}
datasets={[ datasets={[
{ {
label: formatMessage(labels.uniqueVisitors), label: formatMessage(labels.uniqueVisitors),

View File

@ -93,13 +93,12 @@
"node-fetch": "^3.2.8", "node-fetch": "^3.2.8",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"react": "^18.2.0", "react": "^18.2.0",
"react-basics": "^0.71.0", "react-basics": "^0.72.0",
"react-beautiful-dnd": "^13.1.0", "react-beautiful-dnd": "^13.1.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-intl": "^5.24.7", "react-intl": "^5.24.7",
"react-simple-maps": "^2.3.0", "react-simple-maps": "^2.3.0",
"react-spring": "^9.4.4", "react-spring": "^9.4.4",
"react-tooltip": "^4.2.21",
"react-use-measure": "^2.0.4", "react-use-measure": "^2.0.4",
"react-window": "^1.8.6", "react-window": "^1.8.6",
"request-ip": "^3.3.0", "request-ip": "^3.3.0",

View File

@ -7082,10 +7082,10 @@ rc@^1.2.7:
minimist "^1.2.0" minimist "^1.2.0"
strip-json-comments "~2.0.1" strip-json-comments "~2.0.1"
react-basics@^0.71.0: react-basics@^0.72.0:
version "0.71.0" version "0.72.0"
resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.71.0.tgz#317ab58cdbadd4ba36b233cc64dec2a64fe0f1b8" resolved "https://registry.yarnpkg.com/react-basics/-/react-basics-0.72.0.tgz#23dbd61d5ac6bb8b8d61f1f3adcebb7edeab8a26"
integrity sha512-DLhx9bweJz2JG0lETnRrjQNeLL/pmyBqd0SFLM+VXaw8+6SnFheVhQ1Q/W8UerNRsN2oLGH4Hg1XuULG0JlrgA== integrity sha512-dWthEwyh/ilt1BSPYwMdd1oE/OFDp8oZ5udZGrdXs5guRh9Ukar4V4chQPbnuZPYUnAH4jg19H5Fesvz2lSaaw==
dependencies: dependencies:
classnames "^2.3.1" classnames "^2.3.1"
date-fns "^2.29.3" date-fns "^2.29.3"
@ -7198,14 +7198,6 @@ react-spring@^9.5.5:
"@react-spring/web" "~9.5.5" "@react-spring/web" "~9.5.5"
"@react-spring/zdog" "~9.5.5" "@react-spring/zdog" "~9.5.5"
react-tooltip@^4.2.21:
version "4.5.1"
resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.5.1.tgz#77eccccdf16adec804132e558ec20ca5783b866a"
integrity sha512-Zo+CSFUGXar1uV+bgXFFDe7VeS2iByeIp5rTgTcc2HqtuOS5D76QapejNNfx320MCY91TlhTQat36KGFTqgcvw==
dependencies:
prop-types "^15.8.1"
uuid "^7.0.3"
react-use-measure@^2.0.4: react-use-measure@^2.0.4:
version "2.1.1" version "2.1.1"
resolved "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.1.tgz" resolved "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.1.tgz"
@ -8562,11 +8554,6 @@ uuid@3.4.0, uuid@^3.3.2:
resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
uuid@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==
uuid@^8.3.0, uuid@^8.3.2: uuid@^8.3.0, uuid@^8.3.2:
version "8.3.2" version "8.3.2"
resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz"