Skip to content

Commit

Permalink
Merge pull request #1817 from visualize-admin/fix/mobile-tooltip-posi…
Browse files Browse the repository at this point in the history
…tioning

fix: Fixed tooltip for Mobile Area Charts
  • Loading branch information
noahonyejese authored Nov 11, 2024
2 parents 5fc01c0 + 2d6ac36 commit 48d26db
Show file tree
Hide file tree
Showing 15 changed files with 305 additions and 93 deletions.
30 changes: 21 additions & 9 deletions app/charts/area/areas-state.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { extent, group, rollup, sum } from "d3-array";
import {
ScaleLinear,
ScaleOrdinal,
ScaleTime,
scaleLinear,
ScaleOrdinal,
scaleOrdinal,
ScaleTime,
scaleTime,
} from "d3-scale";
import { schemeCategory10 } from "d3-scale-chromatic";
Expand Down Expand Up @@ -40,7 +40,10 @@ import {
InteractiveXTimeRangeState,
} from "@/charts/shared/chart-state";
import { TooltipInfo } from "@/charts/shared/interaction/tooltip";
import { getCenteredTooltipPlacement } from "@/charts/shared/interaction/tooltip-box";
import {
getCenteredTooltipPlacement,
MOBILE_TOOLTIP_PLACEMENT,
} from "@/charts/shared/interaction/tooltip-box";
import {
getStackedTooltipValueFormatter,
getStackedYScale,
Expand All @@ -58,6 +61,7 @@ import {
getSortingOrders,
makeDimensionValueSorters,
} from "@/utils/sorting-values";
import { useIsMobile } from "@/utils/use-is-mobile";

import { ChartProps } from "../shared/ChartProps";

Expand Down Expand Up @@ -352,6 +356,8 @@ const useAreasState = (
xScaleTimeRange.range([0, chartWidth]);
yScale.range([chartHeight, 0]);

const isMobile = useIsMobile();

/** Tooltip */
const getAnnotationInfo = useCallback(
(datum: Observation): TooltipInfo => {
Expand All @@ -372,18 +378,22 @@ const useAreasState = (
formatNumber,
});
const xAnchor = xScale(getX(datum));
const yAnchor = normalize
const yDesktopAnchor = normalize
? yScale.range()[0] * 0.5
: yScale(sum(yValues) * (fields.segment ? 0.5 : 1));
const yAnchor = isMobile ? chartHeight : yDesktopAnchor;
const placement = isMobile
? MOBILE_TOOLTIP_PLACEMENT
: getCenteredTooltipPlacement({
chartWidth,
xAnchor,
topAnchor: !fields.segment,
});

return {
xAnchor,
yAnchor,
placement: getCenteredTooltipPlacement({
chartWidth,
xAnchor,
topAnchor: !fields.segment,
}),
placement,
xValue: timeFormatUnit(getX(datum), xDimension.timeUnit),
datum: {
label: fields.segment && getSegmentAbbreviationOrLabel(datum),
Expand Down Expand Up @@ -420,6 +430,8 @@ const useAreasState = (
normalize,
getIdentityY,
chartWidth,
chartHeight,
isMobile,
]
);

Expand Down
26 changes: 17 additions & 9 deletions app/charts/column/columns-grouped-state.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { extent, group, max, rollup, sum } from "d3-array";
import {
ScaleBand,
ScaleLinear,
ScaleOrdinal,
scaleBand,
ScaleLinear,
scaleLinear,
ScaleOrdinal,
scaleOrdinal,
scaleTime,
} from "d3-scale";
Expand Down Expand Up @@ -34,7 +34,10 @@ import {
InteractiveXTimeRangeState,
} from "@/charts/shared/chart-state";
import { TooltipInfo } from "@/charts/shared/interaction/tooltip";
import { getCenteredTooltipPlacement } from "@/charts/shared/interaction/tooltip-box";
import {
getCenteredTooltipPlacement,
MOBILE_TOOLTIP_PLACEMENT,
} from "@/charts/shared/interaction/tooltip-box";
import useChartFormatters from "@/charts/shared/use-chart-formatters";
import { InteractionProvider } from "@/charts/shared/use-interaction";
import { useSize } from "@/charts/shared/use-size";
Expand All @@ -47,6 +50,7 @@ import {
getSortingOrders,
makeDimensionValueSorters,
} from "@/utils/sorting-values";
import { useIsMobile } from "@/utils/use-is-mobile";

import { ChartProps } from "../shared/ChartProps";

Expand Down Expand Up @@ -359,6 +363,8 @@ const useColumnsGroupedState = (
xScaleTimeRange.range([0, chartWidth]);
yScale.range([chartHeight, 0]);

const isMobile = useIsMobile();

// Tooltip
const getAnnotationInfo = (datum: Observation): TooltipInfo => {
const bw = xScale.bandwidth();
Expand All @@ -383,12 +389,14 @@ const useColumnsGroupedState = (

const xAnchorRaw = (xScale(x) as number) + bw * 0.5;
const [yMin, yMax] = extent(yValues, (d) => d ?? 0) as [number, number];
const yAnchor = yScale((yMin + yMax) * 0.5);
const placement = getCenteredTooltipPlacement({
chartWidth,
xAnchor: xAnchorRaw,
topAnchor: !fields.segment,
});
const yAnchor = isMobile ? chartHeight : yScale((yMin + yMax) * 0.5);
const placement = isMobile
? MOBILE_TOOLTIP_PLACEMENT
: getCenteredTooltipPlacement({
chartWidth,
xAnchor: xAnchorRaw,
topAnchor: !fields.segment,
});

const getError = (d: Observation) => {
if (!showYStandardError || !getYError || getYError(d) == null) {
Expand Down
30 changes: 21 additions & 9 deletions app/charts/column/columns-stacked-state.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { extent, group, rollup, sum } from "d3-array";
import {
ScaleBand,
ScaleLinear,
ScaleOrdinal,
scaleBand,
ScaleLinear,
scaleLinear,
ScaleOrdinal,
scaleOrdinal,
scaleTime,
} from "d3-scale";
Expand Down Expand Up @@ -42,7 +42,10 @@ import {
InteractiveXTimeRangeState,
} from "@/charts/shared/chart-state";
import { TooltipInfo } from "@/charts/shared/interaction/tooltip";
import { getCenteredTooltipPlacement } from "@/charts/shared/interaction/tooltip-box";
import {
getCenteredTooltipPlacement,
MOBILE_TOOLTIP_PLACEMENT,
} from "@/charts/shared/interaction/tooltip-box";
import {
getStackedTooltipValueFormatter,
getStackedYScale,
Expand All @@ -60,6 +63,7 @@ import {
getSortingOrders,
makeDimensionValueSorters,
} from "@/utils/sorting-values";
import { useIsMobile } from "@/utils/use-is-mobile";

import { ChartProps } from "../shared/ChartProps";

Expand Down Expand Up @@ -415,6 +419,8 @@ const useColumnsStackedState = (
xScaleTimeRange.range([0, chartWidth]);
yScale.range([chartHeight, 0]);

const isMobile = useIsMobile();

// Tooltips
const getAnnotationInfo = useCallback(
(datum: Observation): TooltipInfo => {
Expand All @@ -438,12 +444,16 @@ const useColumnsStackedState = (
});

const xAnchorRaw = (xScale(x) as number) + bw * 0.5;
const yAnchor = yScale(sum(yValues.map((d) => d ?? 0)) * 0.5);
const placement = getCenteredTooltipPlacement({
chartWidth,
xAnchor: xAnchorRaw,
topAnchor: !fields.segment,
});
const yAnchor = isMobile
? chartHeight
: yScale(sum(yValues.map((d) => d ?? 0)) * 0.5);
const placement = isMobile
? MOBILE_TOOLTIP_PLACEMENT
: getCenteredTooltipPlacement({
chartWidth,
xAnchor: xAnchorRaw,
topAnchor: !fields.segment,
});

return {
xAnchor: xAnchorRaw + (placement.x === "right" ? 0.5 : -0.5) * bw,
Expand Down Expand Up @@ -479,6 +489,8 @@ const useColumnsStackedState = (
getIdentityY,
colors,
chartWidth,
chartHeight,
isMobile,
normalize,
yScale,
]
Expand Down
28 changes: 20 additions & 8 deletions app/charts/column/columns-state.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { extent, max, rollup, sum } from "d3-array";
import {
ScaleBand,
ScaleLinear,
scaleBand,
ScaleLinear,
scaleLinear,
scaleTime,
} from "d3-scale";
Expand All @@ -27,7 +27,10 @@ import {
InteractiveXTimeRangeState,
} from "@/charts/shared/chart-state";
import { TooltipInfo } from "@/charts/shared/interaction/tooltip";
import { getCenteredTooltipPlacement } from "@/charts/shared/interaction/tooltip-box";
import {
getCenteredTooltipPlacement,
MOBILE_TOOLTIP_PLACEMENT,
} from "@/charts/shared/interaction/tooltip-box";
import useChartFormatters from "@/charts/shared/use-chart-formatters";
import { InteractionProvider } from "@/charts/shared/use-interaction";
import { useSize } from "@/charts/shared/use-size";
Expand All @@ -42,6 +45,7 @@ import {
getSortingOrders,
makeDimensionValueSorters,
} from "@/utils/sorting-values";
import { useIsMobile } from "@/utils/use-is-mobile";

import { ChartProps } from "../shared/ChartProps";

Expand Down Expand Up @@ -217,10 +221,22 @@ const useColumnsState = (
xScaleTimeRange.range([0, chartWidth]);
yScale.range([chartHeight, 0]);

const isMobile = useIsMobile();

// Tooltip
const getAnnotationInfo = (d: Observation): TooltipInfo => {
const xAnchor = (xScale(getX(d)) as number) + xScale.bandwidth() * 0.5;
const yAnchor = yScale(Math.max(getY(d) ?? NaN, 0));
const yAnchor = isMobile
? chartHeight
: yScale(Math.max(getY(d) ?? NaN, 0));
const placement = isMobile
? MOBILE_TOOLTIP_PLACEMENT
: getCenteredTooltipPlacement({
chartWidth,
xAnchor,
topAnchor: !fields.segment,
});

const xLabel = getXAbbreviationOrLabel(d);

const yValueFormatter = (value: number | null) =>
Expand All @@ -243,11 +259,7 @@ const useColumnsState = (
return {
xAnchor,
yAnchor,
placement: getCenteredTooltipPlacement({
chartWidth,
xAnchor,
topAnchor: !fields.segment,
}),
placement,
xValue: xTimeUnit ? timeFormatUnit(xLabel, xTimeUnit) : xLabel,
datum: {
label: undefined,
Expand Down
24 changes: 17 additions & 7 deletions app/charts/combo/combo-line-column-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ import {
InteractiveXTimeRangeState,
} from "@/charts/shared/chart-state";
import { TooltipInfo } from "@/charts/shared/interaction/tooltip";
import { getCenteredTooltipPlacement } from "@/charts/shared/interaction/tooltip-box";
import {
getCenteredTooltipPlacement,
MOBILE_TOOLTIP_PLACEMENT,
} from "@/charts/shared/interaction/tooltip-box";
import { getTickNumber } from "@/charts/shared/ticks";
import { TICK_FONT_SIZE } from "@/charts/shared/use-chart-theme";
import { InteractionProvider } from "@/charts/shared/use-interaction";
Expand All @@ -38,6 +41,7 @@ import { useFormatFullDateAuto } from "@/formatters";
import { TimeUnit } from "@/graphql/resolver-types";
import { getTimeInterval } from "@/intervals";
import { getTextWidth } from "@/utils/get-text-width";
import { useIsMobile } from "@/utils/use-is-mobile";

import { ChartProps } from "../shared/ChartProps";

Expand Down Expand Up @@ -151,6 +155,8 @@ const useComboLineColumnState = (
const yScales = [yScale, yScaleLeft, yScaleRight];
adjustScales(xScales, yScales, { chartWidth, chartHeight });

const isMobile = useIsMobile();

// Tooltip
const getAnnotationInfo = (d: Observation): TooltipInfo => {
const x = getX(d);
Expand All @@ -172,17 +178,21 @@ const useComboLineColumnState = (
};
})
.filter(truthy);
const yAnchor = mean(values.map((d) => d.yPos));
const yAnchor = isMobile ? chartHeight : mean(values.map((d) => d.yPos));
const placement = isMobile
? MOBILE_TOOLTIP_PLACEMENT
: getCenteredTooltipPlacement({
chartWidth,
xAnchor: xScaled,
topAnchor: false,
});

return {
datum: { label: "", value: "0", color: schemeCategory10[0] },
xAnchor: xScaled,
yAnchor,
xValue: timeFormatUnit(x, variables.xTimeUnit as TimeUnit),
placement: getCenteredTooltipPlacement({
chartWidth,
xAnchor: xScaled,
topAnchor: false,
}),
placement,
values,
} as TooltipInfo;
};
Expand Down
Loading

0 comments on commit 48d26db

Please sign in to comment.