Tooltip follows marker on charts with marker (#997)

* Renaming of some tooltip stuff

* Tooltip follows marker on single value history charts
This commit is contained in:
Marshall Polaris 2022-10-04 14:02:44 -07:00 committed by GitHub
parent 26f5e506b7
commit bbce3e873e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 42 additions and 44 deletions

View File

@ -31,9 +31,9 @@ const getBetPoints = (bets: Bet[]) => {
} }
const BinaryChartTooltip = (props: TooltipProps<Date, HistoryPoint<Bet>>) => { const BinaryChartTooltip = (props: TooltipProps<Date, HistoryPoint<Bet>>) => {
const { data, mouseX, xScale } = props const { data, x, xScale } = props
const [start, end] = xScale.domain() const [start, end] = xScale.domain()
const d = xScale.invert(mouseX) const d = xScale.invert(x)
return ( return (
<Row className="items-center gap-2"> <Row className="items-center gap-2">
{data.obj && <Avatar size="xs" avatarUrl={data.obj.userAvatarUrl} />} {data.obj && <Avatar size="xs" avatarUrl={data.obj.userAvatarUrl} />}

View File

@ -180,9 +180,9 @@ export const ChoiceContractChart = (props: {
const ChoiceTooltip = useMemo( const ChoiceTooltip = useMemo(
() => (props: TooltipProps<Date, MultiPoint<Bet>>) => { () => (props: TooltipProps<Date, MultiPoint<Bet>>) => {
const { data, mouseX, xScale } = props const { data, x, xScale } = props
const [start, end] = xScale.domain() const [start, end] = xScale.domain()
const d = xScale.invert(mouseX) const d = xScale.invert(x)
const legendItems = sortBy( const legendItems = sortBy(
data.y.map((p, i) => ({ data.y.map((p, i) => ({
color: CATEGORY_COLORS[i], color: CATEGORY_COLORS[i],

View File

@ -26,11 +26,11 @@ const getNumericChartData = (contract: NumericContract) => {
const NumericChartTooltip = ( const NumericChartTooltip = (
props: TooltipProps<number, DistributionPoint> props: TooltipProps<number, DistributionPoint>
) => { ) => {
const { data, mouseX, xScale } = props const { data, x, xScale } = props
const x = xScale.invert(mouseX) const amount = xScale.invert(x)
return ( return (
<> <>
<span className="text-semibold">{formatLargeNumber(x)}</span> <span className="text-semibold">{formatLargeNumber(amount)}</span>
<span className="text-greyscale-6">{formatPct(data.y, 2)}</span> <span className="text-greyscale-6">{formatPct(data.y, 2)}</span>
</> </>
) )

View File

@ -45,9 +45,9 @@ const getBetPoints = (bets: Bet[], scaleP: (p: number) => number) => {
const PseudoNumericChartTooltip = ( const PseudoNumericChartTooltip = (
props: TooltipProps<Date, HistoryPoint<Bet>> props: TooltipProps<Date, HistoryPoint<Bet>>
) => { ) => {
const { data, mouseX, xScale } = props const { data, x, xScale } = props
const [start, end] = xScale.domain() const [start, end] = xScale.domain()
const d = xScale.invert(mouseX) const d = xScale.invert(x)
return ( return (
<Row className="items-center gap-2"> <Row className="items-center gap-2">
{data.obj && <Avatar size="xs" avatarUrl={data.obj.userAvatarUrl} />} {data.obj && <Avatar size="xs" avatarUrl={data.obj.userAvatarUrl} />}

View File

@ -21,8 +21,8 @@ import {
AreaPath, AreaPath,
AreaWithTopStroke, AreaWithTopStroke,
Point, Point,
MouseProps,
SliceMarker, SliceMarker,
TooltipParams,
TooltipComponent, TooltipComponent,
computeColorStops, computeColorStops,
formatPct, formatPct,
@ -89,7 +89,7 @@ export const DistributionChart = <P extends DistributionPoint>(props: {
}) => { }) => {
const { data, w, h, color, margin, yScale, curve, Tooltip } = props const { data, w, h, color, margin, yScale, curve, Tooltip } = props
const [mouse, setMouse] = useState<MouseProps<P>>() const [ttParams, setTTParams] = useState<TooltipParams<P>>()
const [viewXScale, setViewXScale] = const [viewXScale, setViewXScale] =
useState<ScaleContinuousNumeric<number, number>>() useState<ScaleContinuousNumeric<number, number>>()
const xScale = viewXScale ?? props.xScale const xScale = viewXScale ?? props.xScale
@ -109,13 +109,13 @@ export const DistributionChart = <P extends DistributionPoint>(props: {
const p = selector(mouseX) const p = selector(mouseX)
props.onMouseOver?.(p.prev) props.onMouseOver?.(p.prev)
if (p.prev) { if (p.prev) {
setMouse({ x: mouseX, y: mouseY, data: p.prev }) setTTParams({ x: mouseX, y: mouseY, data: p.prev })
} else { } else {
setMouse(undefined) setTTParams(undefined)
} }
}) })
const onMouseLeave = useEvent(() => setMouse(undefined)) const onMouseLeave = useEvent(() => setTTParams(undefined))
const onSelect = useEvent((ev: D3BrushEvent<P>) => { const onSelect = useEvent((ev: D3BrushEvent<P>) => {
if (ev.selection) { if (ev.selection) {
@ -135,7 +135,7 @@ export const DistributionChart = <P extends DistributionPoint>(props: {
margin={margin} margin={margin}
xAxis={xAxis} xAxis={xAxis}
yAxis={yAxis} yAxis={yAxis}
mouse={mouse} ttParams={ttParams}
onSelect={onSelect} onSelect={onSelect}
onMouseOver={onMouseOver} onMouseOver={onMouseOver}
onMouseLeave={onMouseLeave} onMouseLeave={onMouseLeave}
@ -168,7 +168,7 @@ export const MultiValueHistoryChart = <P extends MultiPoint>(props: {
}) => { }) => {
const { data, w, h, colors, margin, yScale, yKind, curve, Tooltip } = props const { data, w, h, colors, margin, yScale, yKind, curve, Tooltip } = props
const [mouse, setMouse] = useState<MouseProps<P>>() const [ttParams, setTTParams] = useState<TooltipParams<P>>()
const [viewXScale, setViewXScale] = useState<ScaleTime<number, number>>() const [viewXScale, setViewXScale] = useState<ScaleTime<number, number>>()
const xScale = viewXScale ?? props.xScale const xScale = viewXScale ?? props.xScale
@ -208,13 +208,13 @@ export const MultiValueHistoryChart = <P extends MultiPoint>(props: {
const p = selector(mouseX) const p = selector(mouseX)
props.onMouseOver?.(p.prev) props.onMouseOver?.(p.prev)
if (p.prev) { if (p.prev) {
setMouse({ x: mouseX, y: mouseY, data: p.prev }) setTTParams({ x: mouseX, y: mouseY, data: p.prev })
} else { } else {
setMouse(undefined) setTTParams(undefined)
} }
}) })
const onMouseLeave = useEvent(() => setMouse(undefined)) const onMouseLeave = useEvent(() => setTTParams(undefined))
const onSelect = useEvent((ev: D3BrushEvent<P>) => { const onSelect = useEvent((ev: D3BrushEvent<P>) => {
if (ev.selection) { if (ev.selection) {
@ -234,7 +234,7 @@ export const MultiValueHistoryChart = <P extends MultiPoint>(props: {
margin={margin} margin={margin}
xAxis={xAxis} xAxis={xAxis}
yAxis={yAxis} yAxis={yAxis}
mouse={mouse} ttParams={ttParams}
onSelect={onSelect} onSelect={onSelect}
onMouseOver={onMouseOver} onMouseOver={onMouseOver}
onMouseLeave={onMouseLeave} onMouseLeave={onMouseLeave}
@ -272,7 +272,7 @@ export const SingleValueHistoryChart = <P extends HistoryPoint>(props: {
const { data, w, h, color, margin, yScale, yKind, Tooltip } = props const { data, w, h, color, margin, yScale, yKind, Tooltip } = props
const curve = props.curve ?? curveLinear const curve = props.curve ?? curveLinear
const [mouse, setMouse] = useState<MouseProps<P> & SliceExtent>() const [mouse, setMouse] = useState<TooltipParams<P> & SliceExtent>()
const [viewXScale, setViewXScale] = useState<ScaleTime<number, number>>() const [viewXScale, setViewXScale] = useState<ScaleTime<number, number>>()
const xScale = viewXScale ?? props.xScale const xScale = viewXScale ?? props.xScale
@ -299,7 +299,7 @@ export const SingleValueHistoryChart = <P extends HistoryPoint>(props: {
}, [w, h, yKind, xScale, yScale]) }, [w, h, yKind, xScale, yScale])
const selector = dataAtPointSelector(data, xScale) const selector = dataAtPointSelector(data, xScale)
const onMouseOver = useEvent((mouseX: number, mouseY: number) => { const onMouseOver = useEvent((mouseX: number) => {
const p = selector(mouseX) const p = selector(mouseX)
props.onMouseOver?.(p.prev) props.onMouseOver?.(p.prev)
const x0 = p.prev ? xScale(p.prev.x) : xScale.range()[0] const x0 = p.prev ? xScale(p.prev.x) : xScale.range()[0]
@ -310,7 +310,7 @@ export const SingleValueHistoryChart = <P extends HistoryPoint>(props: {
if (p.prev && markerY) { if (p.prev && markerY) {
setMouse({ setMouse({
x: mouseX, x: mouseX,
y: mouseY, y: markerY,
y0: py0, y0: py0,
y1: markerY, y1: markerY,
data: p.prev, data: p.prev,
@ -347,7 +347,9 @@ export const SingleValueHistoryChart = <P extends HistoryPoint>(props: {
margin={margin} margin={margin}
xAxis={xAxis} xAxis={xAxis}
yAxis={yAxis} yAxis={yAxis}
mouse={mouse} ttParams={
mouse ? { x: mouse.x, y: mouse.y, data: mouse.data } : undefined
}
onSelect={onSelect} onSelect={onSelect}
onMouseOver={onMouseOver} onMouseOver={onMouseOver}
onMouseLeave={onMouseLeave} onMouseLeave={onMouseLeave}

View File

@ -144,7 +144,7 @@ export const SVGChart = <X, TT>(props: {
margin: Margin margin: Margin
xAxis: Axis<X> xAxis: Axis<X>
yAxis: Axis<number> yAxis: Axis<number>
mouse: MouseProps<TT> | undefined ttParams: TooltipParams<TT> | undefined
onSelect?: (ev: D3BrushEvent<any>) => void onSelect?: (ev: D3BrushEvent<any>) => void
onMouseOver?: (mouseX: number, mouseY: number) => void onMouseOver?: (mouseX: number, mouseY: number) => void
onMouseLeave?: () => void onMouseLeave?: () => void
@ -157,7 +157,7 @@ export const SVGChart = <X, TT>(props: {
margin, margin,
xAxis, xAxis,
yAxis, yAxis,
mouse, ttParams,
onSelect, onSelect,
onMouseOver, onMouseOver,
onMouseLeave, onMouseLeave,
@ -213,13 +213,13 @@ export const SVGChart = <X, TT>(props: {
return ( return (
<div className="relative overflow-hidden"> <div className="relative overflow-hidden">
{mouse && Tooltip && ( {ttParams && Tooltip && (
<TooltipContainer <TooltipContainer
setElem={tooltipMeasure.setElem} setElem={tooltipMeasure.setElem}
margin={margin} margin={margin}
pos={getTooltipPosition( pos={getTooltipPosition(
mouse.x, ttParams.x,
mouse.y, ttParams.y,
innerW, innerW,
innerH, innerH,
tooltipMeasure.width, tooltipMeasure.width,
@ -228,9 +228,9 @@ export const SVGChart = <X, TT>(props: {
> >
<Tooltip <Tooltip
xScale={xAxis.scale()} xScale={xAxis.scale()}
mouseX={mouse.x} x={ttParams.x}
mouseY={mouse.y} y={ttParams.y}
data={mouse.data} data={ttParams.data}
/> />
</TooltipContainer> </TooltipContainer>
)} )}
@ -287,11 +287,9 @@ export const getTooltipPosition = (
return { left, bottom } return { left, bottom }
} }
export type TooltipProps<X, T> = { export type TooltipParams<T> = { x: number; y: number; data: T }
mouseX: number export type TooltipProps<X, T> = TooltipParams<T> & {
mouseY: number
xScale: ContinuousScale<X> xScale: ContinuousScale<X>
data: T
} }
export type TooltipComponent<X, T> = React.ComponentType<TooltipProps<X, T>> export type TooltipComponent<X, T> = React.ComponentType<TooltipProps<X, T>>
@ -320,8 +318,6 @@ export const TooltipContainer = (props: {
) )
} }
export type MouseProps<T> = { x: number; y: number; data: T }
export const computeColorStops = <P,>( export const computeColorStops = <P,>(
data: P[], data: P[],
pc: (p: P) => string, pc: (p: P) => string,

View File

@ -22,8 +22,8 @@ const getPoints = (startDate: number, dailyValues: number[]) => {
} }
const DailyCountTooltip = (props: TooltipProps<Date, HistoryPoint>) => { const DailyCountTooltip = (props: TooltipProps<Date, HistoryPoint>) => {
const { data, mouseX, xScale } = props const { data, x, xScale } = props
const d = xScale.invert(mouseX) const d = xScale.invert(x)
return ( return (
<Row className="items-center gap-2"> <Row className="items-center gap-2">
<span className="font-semibold">{dayjs(d).format('MMM DD')}</span> <span className="font-semibold">{dayjs(d).format('MMM DD')}</span>
@ -33,8 +33,8 @@ const DailyCountTooltip = (props: TooltipProps<Date, HistoryPoint>) => {
} }
const DailyPercentTooltip = (props: TooltipProps<Date, HistoryPoint>) => { const DailyPercentTooltip = (props: TooltipProps<Date, HistoryPoint>) => {
const { data, mouseX, xScale } = props const { data, x, xScale } = props
const d = xScale.invert(mouseX) const d = xScale.invert(x)
return ( return (
<Row className="items-center gap-2"> <Row className="items-center gap-2">
<span className="font-semibold">{dayjs(d).format('MMM DD')}</span> <span className="font-semibold">{dayjs(d).format('MMM DD')}</span>

View File

@ -18,8 +18,8 @@ const MARGIN_Y = MARGIN.top + MARGIN.bottom
export type GraphMode = 'profit' | 'value' export type GraphMode = 'profit' | 'value'
export const PortfolioTooltip = (props: TooltipProps<Date, HistoryPoint>) => { export const PortfolioTooltip = (props: TooltipProps<Date, HistoryPoint>) => {
const { mouseX, xScale } = props const { x, xScale } = props
const d = dayjs(xScale.invert(mouseX)) const d = dayjs(xScale.invert(x))
return ( return (
<Col className="text-xs font-semibold sm:text-sm"> <Col className="text-xs font-semibold sm:text-sm">
<div>{d.format('MMM/D/YY')}</div> <div>{d.format('MMM/D/YY')}</div>