diff --git a/packages/pxweb2-ui/src/lib/components/Chart/LineChart/LineChart.spec.tsx b/packages/pxweb2-ui/src/lib/components/Chart/LineChart/LineChart.spec.tsx
index 94ad83347..8356601c3 100644
--- a/packages/pxweb2-ui/src/lib/components/Chart/LineChart/LineChart.spec.tsx
+++ b/packages/pxweb2-ui/src/lib/components/Chart/LineChart/LineChart.spec.tsx
@@ -191,8 +191,8 @@ describe('LineChart', () => {
]);
expect(html).toContain('
2024
');
- expect(html).toContain('Men: 10');
- expect(html).toContain('Women: 12');
+ expect(html).toContain('Men:
10');
+ expect(html).toContain('Women:
12');
expect(html).toContain('fill="#666666"');
expect(html).toContain('fill="#ff0000"');
expect(html).toContain('
;
+ data?: Record;
color?: string;
};
+const getConfinedTooltipPosition: NonNullable<
+ echarts.TooltipComponentOption['position']
+> = (point, _params, _dom, _rect, size) => {
+ const padding = 8;
+ const offset = 12;
+
+ const [rawX, rawY] = Array.isArray(point) ? point : [padding, padding];
+
+ const [contentWidth, contentHeight] = size?.contentSize ?? [0, 0];
+ const [viewWidth, viewHeight] = size?.viewSize ?? [0, 0];
+
+ const desiredX = rawX + offset;
+ const desiredY = rawY + offset;
+
+ const maxX = Math.max(padding, viewWidth - contentWidth - padding);
+ const maxY = Math.max(padding, viewHeight - contentHeight - padding);
+
+ const x = Math.min(Math.max(desiredX, padding), maxX);
+ const y = Math.min(Math.max(desiredY, padding), maxY);
+
+ return [x, y];
+};
+
function getTooltipSymbolSvg(symbol: string, color: string): string {
switch (symbol) {
case 'rect':
@@ -41,29 +70,13 @@ function getTooltipSymbolSvg(symbol: string, color: string): string {
}
}
-export function LineChart({ pxtable, colors }: LineChartProps) {
- const dataset = useMemo(() => mapPxTableToChartDataset(pxtable), [pxtable]);
-
- const resolvedColors = useMemo(() => {
- return colors && colors.length > 0
- ? colors
- : getChartColorsFromCssVariables();
- }, [colors]);
-
- const option = useMemo(
- () => ({
- ...buildDatasetOption(dataset),
- grid: { top: 0, bottom: 200, left: '0', right: '0', containLabel: false },
- xAxis: { type: 'category' as const, axisLabel: { rotate: 45 } },
- yAxis: {
- name: dataset.unit,
- min: (value) => value.min,
- },
- legend: {
- height: 40 * dataset.series.length, // increase legend height based on number of series to prevent overlap with x-axis labels
- },
- series: buildSeriesOption(dataset, 'line', resolvedColors),
- tooltip: {
+function getTooltip(
+ tooltipType: TooltipType,
+ dataset: EChartsDataset,
+): echarts.EChartsOption['tooltip'] {
+ switch (tooltipType) {
+ case 'axis':
+ return {
trigger: 'axis',
formatter: (params: unknown) => {
const axisParams = (Array.isArray(params) ? params : [params]) as
@@ -85,15 +98,114 @@ export function LineChart({ pxtable, colors }: LineChartProps) {
];
const color = param.color ?? '#666666';
- return `${getTooltipSymbolSvg(symbol, color)}${param.seriesName}: ${value ?? ''}
`;
+ return `${getTooltipSymbolSvg(symbol, color)}${param.seriesName}: ${value ?? ''}
`;
})
.join('');
return ``;
},
+ };
+ case 'item':
+ return {
+ trigger: 'item',
+ axisPointer: {
+ type: 'cross',
+ },
+ formatter: (params: unknown) => {
+ const param = params as TooltipParam;
+ const seriesMeta = dataset.series[param.seriesIndex];
+
+ if (!seriesMeta) {
+ return '';
+ }
+
+ const row = param.data;
+ const title =
+ param.axisValueLabel ??
+ (param.axisValue != null ? String(param.axisValue) : undefined) ??
+ param.name ??
+ (row?.name != null ? String(row.name) : '');
+ const value = row?.[seriesMeta.key] ?? '';
+ const symbol =
+ LINE_SERIES_SYMBOLS[param.seriesIndex % LINE_SERIES_SYMBOLS.length];
+ const color = param.color ?? '#666666';
+
+ return `
+ ${title}
+
+
+ ${getTooltipSymbolSvg(symbol, color)}
+
+ ${param.seriesName}: ${value}
+
+ `;
+ },
+ };
+ default:
+ return {
+ trigger: 'axis',
+ };
+ }
+}
+
+export function LineChart({
+ pxtable,
+ colors,
+ tooltipType = 'axis',
+}: LineChartProps) {
+ const dataset = useMemo(() => mapPxTableToChartDataset(pxtable), [pxtable]);
+
+ const resolvedColors = useMemo(() => {
+ return colors && colors.length > 0
+ ? colors
+ : getChartColorsFromCssVariables();
+ }, [colors]);
+
+ const series = useMemo(() => {
+ const baseSeries = buildSeriesOption(dataset, 'line', resolvedColors);
+
+ if (tooltipType !== 'item') {
+ return baseSeries;
+ }
+
+ // Show all symbols for 'item' tooltip type to ensure that the tooltip is displayed for all data points
+ return baseSeries.map((seriesOption) => {
+ if (seriesOption.type !== 'line') {
+ return seriesOption;
+ }
+
+ return {
+ ...seriesOption,
+ showSymbol: true,
+ showAllSymbol: true,
+ symbolSize: 7,
+ } as echarts.LineSeriesOption;
+ });
+ }, [dataset, resolvedColors, tooltipType]);
+
+ const option = useMemo(
+ () => ({
+ ...buildDatasetOption(dataset),
+ grid: { top: 0, bottom: 200, left: '0', right: '0', containLabel: false },
+ xAxis: { type: 'category' as const, axisLabel: { rotate: 45 } },
+ yAxis: {
+ name: dataset.unit,
+ min: (value) => value.min,
+ },
+ legend: {
+ height: 40 * dataset.series.length, // increase legend height based on number of series to prevent overlap with x-axis labels
+ },
+ series,
+ tooltip: {
+ ...getTooltip(tooltipType, dataset),
+ confine: true,
+ appendToBody: true,
+ extraCssText:
+ 'max-width:min(92vw,340px);white-space:normal;word-break:break-word;overflow-wrap:anywhere;',
+ position: getConfinedTooltipPosition,
},
}),
- [dataset, resolvedColors],
+ [dataset, series, tooltipType],
);
const { divRef } = useEChartOption(option);
diff --git a/packages/pxweb2/public/config/config.js b/packages/pxweb2/public/config/config.js
index 87ec89910..26a9c5b36 100644
--- a/packages/pxweb2/public/config/config.js
+++ b/packages/pxweb2/public/config/config.js
@@ -38,4 +38,7 @@ globalThis.PxWeb2Config = {
sv: '', // Set to your Swedish homepage URL
en: '', // Set to your English homepage URL
},
+ features: {
+ chartEnabled: true,
+ },
};
diff --git a/packages/pxweb2/src/app/components/Presentation/Presentation.tsx b/packages/pxweb2/src/app/components/Presentation/Presentation.tsx
index 1aa341565..f34092342 100644
--- a/packages/pxweb2/src/app/components/Presentation/Presentation.tsx
+++ b/packages/pxweb2/src/app/components/Presentation/Presentation.tsx
@@ -338,7 +338,8 @@ export function Presentation({
[classes.fadeChart]: isFadingTable,
})}
>
-
+
+
>