From 9bddae17bb8850770cafdfbb08f2eb3d42fa33ec Mon Sep 17 00:00:00 2001 From: Marshall Polaris Date: Sun, 2 Oct 2022 22:23:21 -0700 Subject: [PATCH] Make margins on charts configurable --- web/components/charts/contract/binary.tsx | 7 +++- web/components/charts/contract/choice.tsx | 7 +++- web/components/charts/contract/numeric.tsx | 7 +++- .../charts/contract/pseudo-numeric.tsx | 7 +++- web/components/charts/generic-charts.tsx | 31 ++++++++++---- web/components/charts/helpers.tsx | 41 +++++++++++++------ web/components/charts/stats.tsx | 7 +++- 7 files changed, 77 insertions(+), 30 deletions(-) diff --git a/web/components/charts/contract/binary.tsx b/web/components/charts/contract/binary.tsx index c5bda8d1..b7dc9e18 100644 --- a/web/components/charts/contract/binary.tsx +++ b/web/components/charts/contract/binary.tsx @@ -9,8 +9,6 @@ import { BinaryContract } from 'common/contract' import { DAY_MS } from 'common/util/time' import { TooltipProps, - MARGIN_X, - MARGIN_Y, getDateRange, getRightmostVisibleDate, formatDateInRange, @@ -20,6 +18,10 @@ import { HistoryPoint, SingleValueHistoryChart } from '../generic-charts' import { Row } from 'web/components/layout/row' import { Avatar } from 'web/components/avatar' +const MARGIN = { top: 20, right: 10, bottom: 20, left: 40 } +const MARGIN_X = MARGIN.left + MARGIN.right +const MARGIN_Y = MARGIN.top + MARGIN.bottom + const getBetPoints = (bets: Bet[]) => { return sortBy(bets, (b) => b.createdTime).map((b) => ({ x: new Date(b.createdTime), @@ -73,6 +75,7 @@ export const BinaryContractChart = (props: { { const { totalShares, bucketCount, min, max } = contract const step = (max - min) / bucketCount @@ -48,6 +52,7 @@ export const NumericContractChart = (props: { (props: { w: number h: number color: string + margin: Margin xScale: ScaleContinuousNumeric yScale: ScaleContinuousNumeric curve?: CurveFactory onMouseOver?: (p: P | undefined) => void Tooltip?: TooltipComponent }) => { - const { color, data, yScale, w, h, curve, Tooltip } = props + const { data, w, h, color, margin, yScale, curve, Tooltip } = props const [viewXScale, setViewXScale] = useState>() @@ -96,6 +98,7 @@ export const DistributionChart =

(props: { (props: { w: number h: number colors: readonly string[] + margin: Margin xScale: ScaleTime yScale: ScaleContinuousNumeric yKind?: ValueKind @@ -126,7 +130,7 @@ export const MultiValueHistoryChart =

(props: { onMouseOver?: (p: P | undefined) => void Tooltip?: TooltipComponent }) => { - const { colors, data, yScale, yKind, w, h, curve, Tooltip } = props + const { data, w, h, colors, margin, yScale, yKind, curve, Tooltip } = props const [viewXScale, setViewXScale] = useState>() const xScale = viewXScale ?? props.xScale @@ -138,7 +142,8 @@ export const MultiValueHistoryChart =

(props: { const { xAxis, yAxis } = useMemo(() => { const [min, max] = yScale.domain() - const pctTickValues = getTickValues(min, max, h < 200 ? 3 : 5) + const nTicks = h < 200 ? 3 : 5 + const pctTickValues = getTickValues(min, max, nTicks) const xAxis = axisBottom(xScale).ticks(w / 100) const yAxis = yKind === 'percent' @@ -146,8 +151,10 @@ export const MultiValueHistoryChart =

(props: { .tickValues(pctTickValues) .tickFormat((n) => formatPct(n)) : yKind === 'm$' - ? axisLeft(yScale).tickFormat((n) => formatMoney(n)) - : axisLeft(yScale) + ? axisLeft(yScale) + .ticks(nTicks) + .tickFormat((n) => formatMoney(n)) + : axisLeft(yScale).ticks(nTicks) return { xAxis, yAxis } }, [w, h, yKind, xScale, yScale]) @@ -181,6 +188,7 @@ export const MultiValueHistoryChart =

(props: { (props: { w: number h: number color: string + margin: Margin xScale: ScaleTime yScale: ScaleContinuousNumeric yKind?: ValueKind @@ -215,7 +224,7 @@ export const SingleValueHistoryChart =

(props: { Tooltip?: TooltipComponent pct?: boolean }) => { - const { color, data, yScale, yKind, w, h, curve, Tooltip } = props + const { data, w, h, color, margin, yScale, yKind, curve, Tooltip } = props const [viewXScale, setViewXScale] = useState>() const xScale = viewXScale ?? props.xScale @@ -226,7 +235,8 @@ export const SingleValueHistoryChart =

(props: { const { xAxis, yAxis } = useMemo(() => { const [min, max] = yScale.domain() - const pctTickValues = getTickValues(min, max, h < 200 ? 3 : 5) + const nTicks = h < 200 ? 3 : 5 + const pctTickValues = getTickValues(min, max, nTicks) const xAxis = axisBottom(xScale).ticks(w / 100) const yAxis = yKind === 'percent' @@ -234,8 +244,10 @@ export const SingleValueHistoryChart =

(props: { .tickValues(pctTickValues) .tickFormat((n) => formatPct(n)) : yKind === 'm$' - ? axisLeft(yScale).tickFormat((n) => formatMoney(n)) - : axisLeft(yScale) + ? axisLeft(yScale) + .ticks(nTicks) + .tickFormat((n) => formatMoney(n)) + : axisLeft(yScale).ticks(nTicks) return { xAxis, yAxis } }, [w, h, yKind, xScale, yScale]) @@ -261,6 +273,7 @@ export const SingleValueHistoryChart =

(props: { extends AxisScale { export type XScale

= P extends Point ? AxisScale : never export type YScale

= P extends Point ? AxisScale : never -export const MARGIN = { top: 20, right: 10, bottom: 20, left: 40 } -export const MARGIN_X = MARGIN.right + MARGIN.left -export const MARGIN_Y = MARGIN.top + MARGIN.bottom -const MARGIN_STYLE = `${MARGIN.top}px ${MARGIN.right}px ${MARGIN.bottom}px ${MARGIN.left}px` -const MARGIN_XFORM = `translate(${MARGIN.left}, ${MARGIN.top})` +export type Margin = { + top: number + right: number + bottom: number + left: number +} export const XAxis = (props: { w: number; h: number; axis: Axis }) => { const { h, axis } = props @@ -55,8 +56,6 @@ export const YAxis = (props: { w: number; h: number; axis: Axis }) => { useEffect(() => { if (axisRef.current != null) { select(axisRef.current) - .transition() - .duration(250) .call(axis) .call((g) => g.selectAll('.tick line').attr('x2', w).attr('stroke-opacity', 0.1) @@ -128,18 +127,29 @@ export const SVGChart = (props: { children: ReactNode w: number h: number + margin: Margin xAxis: Axis yAxis: Axis onSelect?: (ev: D3BrushEvent) => void onMouseOver?: (mouseX: number, mouseY: number) => TT | undefined Tooltip?: TooltipComponent }) => { - const { children, w, h, xAxis, yAxis, onMouseOver, onSelect, Tooltip } = props + const { + children, + w, + h, + margin, + xAxis, + yAxis, + onMouseOver, + onSelect, + Tooltip, + } = props const [mouse, setMouse] = useState<{ x: number; y: number; data: TT }>() const tooltipMeasure = useMeasureSize() const overlayRef = useRef(null) - const innerW = w - MARGIN_X - const innerH = h - MARGIN_Y + const innerW = w - (margin.left + margin.right) + const innerH = h - (margin.top + margin.bottom) const clipPathId = useMemo(() => nanoid(), []) const justSelected = useRef(false) @@ -194,6 +204,7 @@ export const SVGChart = (props: { {mouse && Tooltip && ( (props: { - + {children} @@ -275,10 +286,11 @@ export type TooltipComponent = React.ComponentType> export const TooltipContainer = (props: { setElem: (e: HTMLElement | null) => void pos: TooltipPosition + margin: Margin className?: string children: React.ReactNode }) => { - const { setElem, pos, className, children } = props + const { setElem, pos, margin, className, children } = props return (

{children}
diff --git a/web/components/charts/stats.tsx b/web/components/charts/stats.tsx index 544f39c6..eb3999d8 100644 --- a/web/components/charts/stats.tsx +++ b/web/components/charts/stats.tsx @@ -6,9 +6,13 @@ import dayjs from 'dayjs' import { formatPercent } from 'common/util/format' import { Row } from '../layout/row' import { HistoryPoint, SingleValueHistoryChart } from './generic-charts' -import { TooltipProps, MARGIN_X, MARGIN_Y } from './helpers' +import { TooltipProps } from './helpers' import { SizedContainer } from 'web/components/sized-container' +const MARGIN = { top: 20, right: 10, bottom: 20, left: 40 } +const MARGIN_X = MARGIN.left + MARGIN.right +const MARGIN_Y = MARGIN.top + MARGIN.bottom + const getPoints = (startDate: number, dailyValues: number[]) => { const startDateDayJs = dayjs(startDate) return dailyValues.map((y, i) => ({ @@ -63,6 +67,7 @@ export function DailyChart(props: {