diff --git a/front_end/src/components/charts/continuous_area_chart.tsx b/front_end/src/components/charts/continuous_area_chart.tsx index fd94724446..f888574038 100644 --- a/front_end/src/components/charts/continuous_area_chart.tsx +++ b/front_end/src/components/charts/continuous_area_chart.tsx @@ -25,7 +25,9 @@ import { VictoryThemeDefinition, } from "victory"; +import { CHART_DASH } from "@/constants/chart_dash"; import { darkTheme, lightTheme } from "@/constants/chart_theme"; +import { CHART_FONT_STYLE } from "@/constants/chart_typography"; import { METAC_COLORS } from "@/constants/colors"; import useAppTheme from "@/hooks/use_app_theme"; import useContainerSize from "@/hooks/use_container_size"; @@ -729,7 +731,9 @@ const ContinuousAreaChart: FC = ({ } })(), strokeDasharray: - chart.type === "user_previous" ? "2,2" : undefined, + chart.type === "user_previous" + ? CHART_DASH.quartile + : undefined, }, }} /> @@ -740,8 +744,10 @@ const ContinuousAreaChart: FC = ({ = ({ }} tickValues={yScale.ticks} tickFormat={yScale.tickFormat} - axisValue={xDomain[0]} + axisValue={xDomain[1]} /> )} @@ -773,7 +779,7 @@ const ContinuousAreaChart: FC = ({ strokeWidth: 0, }, tickLabels: { - fontSize: 10, + ...CHART_FONT_STYLE.tick, fill: getThemeColor(METAC_COLORS.gray["700"]), textAnchor: ({ index, ticks }) => // We want first and last labels be aligned against area boundaries @@ -867,7 +873,7 @@ const ContinuousAreaChart: FC = ({ return undefined; } })(), - strokeDasharray: "2,2", + strokeDasharray: CHART_DASH.quartile, }, }} /> diff --git a/front_end/src/components/charts/fan_chart.tsx b/front_end/src/components/charts/fan_chart.tsx index 633af04d31..2be3565931 100644 --- a/front_end/src/components/charts/fan_chart.tsx +++ b/front_end/src/components/charts/fan_chart.tsx @@ -8,7 +8,6 @@ import { VictoryAxis, VictoryChart, VictoryContainer, - VictoryLabel, VictoryLine, VictoryPortal, VictoryScatter, @@ -21,6 +20,7 @@ import FanPoint from "@/components/charts/primitives/fan_point"; import PredictionWithRange from "@/components/charts/primitives/prediction_with_range"; import ResolutionDiamond from "@/components/charts/primitives/resolution_diamond"; import ForecastAvailabilityChartOverflow from "@/components/post_card/chart_overflow"; +import { CHART_DASH } from "@/constants/chart_dash"; import { darkTheme, lightTheme } from "@/constants/chart_theme"; import { METAC_COLORS } from "@/constants/colors"; import useAppTheme from "@/hooks/use_app_theme"; @@ -475,7 +475,7 @@ const FanChart: FC = ({ > = ({ ...baseYAxisStyle, grid: isEmbedded ? { display: "none" } : baseYAxisStyle?.grid, }} - offsetX={ - isEmbedded ? undefined : v.axisLabelOffsetX(variantArgs) - } - axisLabelComponent={ - isEmbedded ? undefined : - } /> {isEmbedded && embedGridTicks && ( @@ -507,7 +501,7 @@ const FanChart: FC = ({ }, grid: { ...baseYAxisStyle?.grid, - strokeDasharray: "2,4", + strokeDasharray: CHART_DASH.grid, }, }} /> diff --git a/front_end/src/components/charts/fan_chart_variants.ts b/front_end/src/components/charts/fan_chart_variants.ts index ed666c09e6..e4f12f5f8c 100644 --- a/front_end/src/components/charts/fan_chart_variants.ts +++ b/front_end/src/components/charts/fan_chart_variants.ts @@ -1,6 +1,9 @@ import { ComponentProps } from "react"; import { VictoryAxis } from "victory"; +import { CHART_DASH } from "@/constants/chart_dash"; +import { CHART_POINT_SIZE, CHART_STROKE_WIDTH } from "@/constants/chart_stroke"; +import { CHART_FONT_STYLE } from "@/constants/chart_typography"; import { METAC_COLORS } from "@/constants/colors"; import { ThemeColor } from "@/types/theme"; @@ -61,12 +64,12 @@ export const fanVariants: Record = { yAxisStyle: ({ getThemeColor, tickLabelFontSize }) => ({ ticks: { stroke: "transparent" }, axisLabel: { - fontFamily: "Inter", + ...CHART_FONT_STYLE.axisLabel, fontSize: tickLabelFontSize, fill: getThemeColor(METAC_COLORS.gray["600"]), }, tickLabels: { - fontFamily: "Inter", + ...CHART_FONT_STYLE.tick, padding: 5, fontSize: tickLabelFontSize, fill: getThemeColor(METAC_COLORS.gray["600"]), @@ -74,8 +77,8 @@ export const fanVariants: Record = { axis: { stroke: "transparent" }, grid: { stroke: getThemeColor(METAC_COLORS.gray["400"]), - strokeWidth: 1, - strokeDasharray: "2, 5", + strokeWidth: CHART_STROKE_WIDTH.grid, + strokeDasharray: CHART_DASH.grid, }, }), xAxisStyle: () => ({ @@ -84,13 +87,13 @@ export const fanVariants: Record = { }), domainPadding: ({ isEmbedded }) => isEmbedded ? { x: [16, 16] } : { x: [150 / 2, 150 / 2] }, - padding: ({ maxLeftPadding }) => ({ - left: maxLeftPadding, + padding: ({ maxRightPadding }) => ({ + left: 10, top: 10, - right: 10, + right: maxRightPadding, bottom: 20, }), - axisLabelOffsetX: ({ maxLeftPadding }) => Math.max(maxLeftPadding - 2, 8), + axisLabelOffsetX: () => 0, palette: ({ getThemeColor, isEmbedded }) => ({ communityArea: getThemeColor(METAC_COLORS.olive["500"]), communityLine: getThemeColor(METAC_COLORS.olive["800"]), @@ -102,8 +105,8 @@ export const fanVariants: Record = { : getThemeColor(METAC_COLORS.olive["800"]), }), resolutionPoint: { - size: 10, - strokeWidth: 2.5, + size: CHART_POINT_SIZE.resolutionDiamond, + strokeWidth: CHART_STROKE_WIDTH.resolutionDiamond, fill: () => "none", }, }, @@ -112,12 +115,12 @@ export const fanVariants: Record = { yAxisStyle: ({ tickLabelFontSize, getThemeColor }) => ({ ticks: { stroke: "transparent" }, axisLabel: { - fontFamily: "Inter", + ...CHART_FONT_STYLE.axisLabel, fontSize: tickLabelFontSize, fill: getThemeColor(METAC_COLORS.gray["600"]), }, tickLabels: { - fontFamily: "Inter", + ...CHART_FONT_STYLE.tick, padding: 5, fontSize: tickLabelFontSize, fill: getThemeColor(METAC_COLORS.gray["600"]), @@ -125,15 +128,15 @@ export const fanVariants: Record = { axis: { stroke: "transparent" }, grid: { stroke: getThemeColor(METAC_COLORS.gray["400"]), - strokeWidth: 1, - strokeDasharray: "2, 5", + strokeWidth: CHART_STROKE_WIDTH.grid, + strokeDasharray: CHART_DASH.grid, }, }), xAxisStyle: ({ tickLabelFontSize, getThemeColor }) => ({ ticks: { stroke: "transparent" }, axis: { stroke: "transparent" }, tickLabels: { - fontFamily: "Inter", + ...CHART_FONT_STYLE.tick, fontSize: tickLabelFontSize, fill: getThemeColor(METAC_COLORS.gray["600"]), }, @@ -142,11 +145,10 @@ export const fanVariants: Record = { padding: ({ maxRightPadding }) => ({ left: 10, top: 10, - right: maxRightPadding - 10, + right: maxRightPadding, bottom: 15, }), - axisLabelOffsetX: ({ chartWidth, yLabel, tickLabelFontSize }) => - !yLabel ? chartWidth + 5 : chartWidth - tickLabelFontSize + 5, + axisLabelOffsetX: () => 0, forceTickCount: 5, palette: ({ getThemeColor }) => ({ communityArea: getThemeColor(METAC_COLORS.blue["500"]), @@ -157,8 +159,8 @@ export const fanVariants: Record = { communityPoint: getThemeColor(METAC_COLORS.blue["700"]), }), resolutionPoint: { - size: 13, - strokeWidth: 3, + size: CHART_POINT_SIZE.resolutionDiamond, + strokeWidth: CHART_STROKE_WIDTH.resolutionDiamond, fill: ({ getThemeColor }) => getThemeColor(METAC_COLORS.purple["800"]), }, }, diff --git a/front_end/src/components/charts/group_chart.tsx b/front_end/src/components/charts/group_chart.tsx index 72c1f40d88..4e3fac0f73 100644 --- a/front_end/src/components/charts/group_chart.tsx +++ b/front_end/src/components/charts/group_chart.tsx @@ -13,7 +13,6 @@ import { VictoryChart, VictoryContainer, VictoryCursorContainer, - VictoryLabel, VictoryLabelProps, VictoryLine, VictoryPortal, @@ -21,7 +20,9 @@ import { VictoryThemeDefinition, } from "victory"; +import { CHART_DASH } from "@/constants/chart_dash"; import { darkTheme, lightTheme } from "@/constants/chart_theme"; +import { CHART_FONT_STYLE } from "@/constants/chart_typography"; import { METAC_COLORS } from "@/constants/colors"; import useAppTheme from "@/hooks/use_app_theme"; import useContainerSize from "@/hooks/use_container_size"; @@ -92,9 +93,7 @@ type Props = { leftPadding?: number; }; -const LABEL_FONT_FAMILY = "Inter"; const BOTTOM_PADDING = 20; -const TICK_FONT_SIZE = 10; const POINT_SIZE = 9; const USER_POINT_SIZE = 6; const USER_POINT_STROKE = 1.5; @@ -297,7 +296,7 @@ const GroupChart: FC = ({ isCursorActive ? { stroke: getThemeColor(METAC_COLORS.gray["600"]), - strokeDasharray: "2,1", + strokeDasharray: CHART_DASH.cursor, } : { stroke: "transparent", @@ -414,12 +413,12 @@ const GroupChart: FC = ({ stroke: "transparent", }, axisLabel: { - fontFamily: LABEL_FONT_FAMILY, + ...CHART_FONT_STYLE.axisLabel, fontSize: tickLabelFontSize, fill: getThemeColor(METAC_COLORS.gray["500"]), }, tickLabels: { - fontFamily: LABEL_FONT_FAMILY, + ...CHART_FONT_STYLE.tick, padding: 5, fontSize: tickLabelFontSize, fill: getThemeColor(METAC_COLORS.gray["700"]), @@ -430,17 +429,11 @@ const GroupChart: FC = ({ grid: { stroke: getThemeColor(METAC_COLORS.gray["400"]), strokeWidth: 1, - strokeDasharray: "3, 2", + strokeDasharray: CHART_DASH.grid, }, }} label={yLabel} - offsetX={ - isNil(yLabel) - ? chartWidth + 5 - : chartWidth - TICK_FONT_SIZE + 5 - } - orientation={"left"} - axisLabelComponent={} + orientation="right" /> {/* X axis */} @@ -467,7 +460,7 @@ const GroupChart: FC = ({ stroke: "transparent", }, tickLabels: { - fontFamily: LABEL_FONT_FAMILY, + ...CHART_FONT_STYLE.tick, padding: 5, fontSize: tickLabelFontSize, fill: getThemeColor(METAC_COLORS.gray["700"]), diff --git a/front_end/src/components/charts/histogram.tsx b/front_end/src/components/charts/histogram.tsx index 46db82290a..7a459c81cf 100644 --- a/front_end/src/components/charts/histogram.tsx +++ b/front_end/src/components/charts/histogram.tsx @@ -13,6 +13,7 @@ import { } from "victory"; import { darkTheme, lightTheme } from "@/constants/chart_theme"; +import { CHART_FONT_STYLE } from "@/constants/chart_typography"; import { METAC_COLORS } from "@/constants/colors"; import useAppTheme from "@/hooks/use_app_theme"; import useContainerSize from "@/hooks/use_container_size"; @@ -173,7 +174,7 @@ const Histogram: React.FC = ({ } style={{ tickLabels: { - fontSize: 10, + ...CHART_FONT_STYLE.tick, fontWeight: 400, fill: getThemeColor(METAC_COLORS.gray["700"]), }, diff --git a/front_end/src/components/charts/minified_continuous_area_chart.tsx b/front_end/src/components/charts/minified_continuous_area_chart.tsx index 16f3aa586d..ed07109d35 100644 --- a/front_end/src/components/charts/minified_continuous_area_chart.tsx +++ b/front_end/src/components/charts/minified_continuous_area_chart.tsx @@ -13,7 +13,9 @@ import { VictoryThemeDefinition, } from "victory"; +import { CHART_DASH } from "@/constants/chart_dash"; import { darkTheme, lightTheme } from "@/constants/chart_theme"; +import { CHART_FONT_STYLE } from "@/constants/chart_typography"; import { METAC_COLORS } from "@/constants/colors"; import useAppTheme from "@/hooks/use_app_theme"; import useContainerSize from "@/hooks/use_container_size"; @@ -421,9 +423,10 @@ const MinifiedContinuousAreaChart: FC = ({ axis: { stroke: getThemeColor(METAC_COLORS.olive["100"]), strokeWidth: 0, - strokeDasharray: "4, 4", + strokeDasharray: CHART_DASH.grid, }, tickLabels: { + ...CHART_FONT_STYLE.tick, fontSize: variant === "feed" ? 10 : 8, textAnchor: ({ index, ticks }) => // We want first and last labels be aligned against area boundaries @@ -433,7 +436,6 @@ const MinifiedContinuousAreaChart: FC = ({ ? "end" : "middle", fill: getThemeColor(METAC_COLORS.gray["500"]), - fontFamily: "Inter", }, }} /> diff --git a/front_end/src/components/charts/multiple_choice_chart.tsx b/front_end/src/components/charts/multiple_choice_chart.tsx index 7357758540..267a74adb2 100644 --- a/front_end/src/components/charts/multiple_choice_chart.tsx +++ b/front_end/src/components/charts/multiple_choice_chart.tsx @@ -21,7 +21,6 @@ import { VictoryChart, VictoryContainer, VictoryCursorContainer, - VictoryLabel, VictoryLabelProps, VictoryPortal, VictoryScatter, @@ -29,7 +28,9 @@ import { VictoryThemeDefinition, } from "victory"; +import { CHART_DASH } from "@/constants/chart_dash"; import { darkTheme, lightTheme } from "@/constants/chart_theme"; +import { CHART_FONT_STYLE } from "@/constants/chart_typography"; import { METAC_COLORS } from "@/constants/colors"; import useAppTheme from "@/hooks/use_app_theme"; import useContainerSize from "@/hooks/use_container_size"; @@ -100,9 +101,7 @@ type Props = { leftPadding?: number; }; -const LABEL_FONT_FAMILY = "Inter"; const BOTTOM_PADDING = 20; -const TICK_FONT_SIZE = 10; const MultipleChoiceChart: FC = ({ timestamps, @@ -242,7 +241,7 @@ const MultipleChoiceChart: FC = ({ isCursorActive ? { stroke: getThemeColor(METAC_COLORS.gray["600"]), - strokeDasharray: "2,1", + strokeDasharray: CHART_DASH.cursor, } : { stroke: "transparent", @@ -389,12 +388,12 @@ const MultipleChoiceChart: FC = ({ stroke: "transparent", }, axisLabel: { - fontFamily: LABEL_FONT_FAMILY, + ...CHART_FONT_STYLE.axisLabel, fontSize: tickLabelFontSize, fill: getThemeColor(METAC_COLORS.gray["500"]), }, tickLabels: { - fontFamily: LABEL_FONT_FAMILY, + ...CHART_FONT_STYLE.tick, padding: 5, fontSize: tickLabelFontSize, fill: getThemeColor(METAC_COLORS.gray["700"]), @@ -406,18 +405,14 @@ const MultipleChoiceChart: FC = ({ ? { stroke: getThemeColor(METAC_COLORS.gray["300"]), strokeWidth: 1, - strokeDasharray: "2, 5", + strokeDasharray: CHART_DASH.grid, } : { stroke: "transparent", }, }} label={yLabel} - offsetX={ - isNil(yLabel) ? chartWidth + 5 : chartWidth - TICK_FONT_SIZE + 5 - } - orientation={"left"} - axisLabelComponent={} + orientation="right" /> = ({ stroke: "transparent", }, tickLabels: { + ...CHART_FONT_STYLE.tick, fill: getThemeColor(METAC_COLORS.gray["700"]), }, }} diff --git a/front_end/src/components/charts/numeric_chart.tsx b/front_end/src/components/charts/numeric_chart.tsx index a079083335..0088f58b83 100644 --- a/front_end/src/components/charts/numeric_chart.tsx +++ b/front_end/src/components/charts/numeric_chart.tsx @@ -19,7 +19,6 @@ import { VictoryChart, VictoryContainer, VictoryCursorContainer, - VictoryLabel, VictoryLabelProps, VictoryLine, VictoryPortal, @@ -36,7 +35,12 @@ import { clusterAnnotations } from "@/components/charts/primitives/news_annotati import PredictionWithRange from "@/components/charts/primitives/prediction_with_range"; import ResolutionDiamond from "@/components/charts/primitives/resolution_diamond"; import XTickLabel from "@/components/charts/primitives/x_tick_label"; +import { CHART_DASH } from "@/constants/chart_dash"; import { darkTheme, lightTheme } from "@/constants/chart_theme"; +import { + CHART_FONT_SIZE, + CHART_FONT_STYLE, +} from "@/constants/chart_typography"; import { METAC_COLORS } from "@/constants/colors"; import useAppTheme from "@/hooks/use_app_theme"; import useChartTooltip from "@/hooks/use_chart_tooltip"; @@ -105,7 +109,6 @@ type Props = { const BOTTOM_PADDING = 20; const NEWS_ANNOTATION_MARKER_SIZE = 18; -const LABEL_FONT_FAMILY = "Inter"; const NumericChart: FC = ({ buildChartData, @@ -116,7 +119,7 @@ const NumericChart: FC = ({ withZoomPicker = false, resolutionPoint, yLabel, - tickFontSize = 10, + tickFontSize = CHART_FONT_SIZE.tick, extraTheme, onChartReady, cursorTimestamp, @@ -256,7 +259,7 @@ const NumericChart: FC = ({ style={{ stroke: getThemeColor(METAC_COLORS.blue["700"]), opacity: 0.5, - strokeDasharray: "5,2", + strokeDasharray: CHART_DASH.cursor, }} /> } @@ -267,9 +270,7 @@ const NumericChart: FC = ({ {...(hasExternalTheme ? {} : { fill: getThemeColor(METAC_COLORS.gray["700"]) })} - style={{ - fontFamily: LABEL_FONT_FAMILY, - }} + style={CHART_FONT_STYLE.cursor} isActive={isCursorActive} /> @@ -594,7 +595,7 @@ const NumericChart: FC = ({ {/* Y axis used for GRIDLINES */} = ({ grid: { stroke: getThemeColor(METAC_COLORS.gray["400"]), strokeWidth: 1, - strokeDasharray: "3, 2", + strokeDasharray: CHART_DASH.grid, }, }} tickValues={yScaleTicks} @@ -617,14 +618,14 @@ const NumericChart: FC = ({ axis: { stroke: "transparent" }, grid: { stroke: "transparent" }, axisLabel: { - fontFamily: LABEL_FONT_FAMILY, + ...CHART_FONT_STYLE.axisLabel, fontSize: tickLabelFontSize, ...(hasExternalTheme ? {} : { fill: getThemeColor(METAC_COLORS.gray["500"]) }), }, tickLabels: { - fontFamily: LABEL_FONT_FAMILY, + ...CHART_FONT_STYLE.tick, padding: 5, fontSize: tickLabelFontSize, ...(hasExternalTheme @@ -635,13 +636,7 @@ const NumericChart: FC = ({ tickValues={yScaleTicks} tickFormat={yScale.tickFormat} label={yAxisLabel} - orientation={"left"} - offsetX={ - isNil(yLabel) - ? chartWidth + 5 - : chartWidth - tickLabelFontSize + 5 - } - axisLabelComponent={} + orientation="right" /> {/* X axis */} @@ -667,7 +662,7 @@ const NumericChart: FC = ({ fontSize={tickLabelFontSize} {...(!extraTheme && { style: { - fontFamily: LABEL_FONT_FAMILY, + ...CHART_FONT_STYLE.tick, fill: getThemeColor(METAC_COLORS.gray["700"]), }, })} diff --git a/front_end/src/components/charts/primitives/fan_point.tsx b/front_end/src/components/charts/primitives/fan_point.tsx index 066d948cc1..91b8b70cc3 100644 --- a/front_end/src/components/charts/primitives/fan_point.tsx +++ b/front_end/src/components/charts/primitives/fan_point.tsx @@ -4,6 +4,7 @@ import { isNil } from "lodash"; import { ComponentProps, FC } from "react"; import { Point } from "victory"; +import { CHART_DASH } from "@/constants/chart_dash"; import { METAC_COLORS } from "@/constants/colors"; import useAppTheme from "@/hooks/use_app_theme"; @@ -147,7 +148,7 @@ const FanPoint: FC = ({ y2={`calc(100% - ${bottomPadding}px)`} stroke={getThemeColor(METAC_COLORS.blue["700"])} strokeWidth={1} - strokeDasharray="6 2" + strokeDasharray={CHART_DASH.cursor} opacity={0.5} /> )} diff --git a/front_end/src/components/charts/primitives/group_resolution_point.tsx b/front_end/src/components/charts/primitives/group_resolution_point.tsx index 30156cac38..1e1cc35d6f 100644 --- a/front_end/src/components/charts/primitives/group_resolution_point.tsx +++ b/front_end/src/components/charts/primitives/group_resolution_point.tsx @@ -4,6 +4,7 @@ import { isNil } from "lodash"; import { ComponentProps, FC } from "react"; import { Point } from "victory"; +import { CHART_DASH } from "@/constants/chart_dash"; import { METAC_COLORS } from "@/constants/colors"; import useAppTheme from "@/hooks/use_app_theme"; @@ -64,7 +65,7 @@ const GroupResolutionPoint: FC = ({ y2={y - (text ? textOffset : 0)} stroke={strokeColor} strokeWidth={1} - strokeDasharray="2 2" + strokeDasharray={CHART_DASH.threshold} opacity={1} /> )} diff --git a/front_end/src/components/charts/primitives/resolution_diamond.tsx b/front_end/src/components/charts/primitives/resolution_diamond.tsx index 02c866033d..066b78e840 100644 --- a/front_end/src/components/charts/primitives/resolution_diamond.tsx +++ b/front_end/src/components/charts/primitives/resolution_diamond.tsx @@ -2,6 +2,7 @@ import { isNil } from "lodash"; import React, { forwardRef, memo } from "react"; +import { CHART_DASH } from "@/constants/chart_dash"; import { METAC_COLORS } from "@/constants/colors"; import useAppTheme from "@/hooks/use_app_theme"; import { ThemeColor } from "@/types/theme"; @@ -136,7 +137,7 @@ const ResolutionDiamond = forwardRef(function RD( y2={scale.y(d.y)} stroke={darkColor} strokeWidth={1} - strokeDasharray="2 2" + strokeDasharray={CHART_DASH.threshold} opacity={1} /> )} diff --git a/front_end/src/components/charts/primitives/timeline_markers/group_timeline_markers_overlay.tsx b/front_end/src/components/charts/primitives/timeline_markers/group_timeline_markers_overlay.tsx index 7dc0ffd5ca..9b1b7fcce8 100644 --- a/front_end/src/components/charts/primitives/timeline_markers/group_timeline_markers_overlay.tsx +++ b/front_end/src/components/charts/primitives/timeline_markers/group_timeline_markers_overlay.tsx @@ -4,6 +4,7 @@ import { faComment, faNewspaper } from "@fortawesome/free-solid-svg-icons"; import { ReactNode } from "react"; import { VictoryLine, VictoryPortal, VictoryScatter } from "victory"; +import { CHART_DASH } from "@/constants/chart_dash"; import { METAC_COLORS } from "@/constants/colors"; import { ThemeColor } from "@/types/theme"; @@ -137,7 +138,7 @@ export function renderGroupTimelineMarkers({ style={{ data: { stroke: lineColor, - strokeDasharray: "4,3", + strokeDasharray: CHART_DASH.timelineMarker, strokeWidth: 1.5, pointerEvents: "none", }, diff --git a/front_end/src/constants/chart_dash.ts b/front_end/src/constants/chart_dash.ts new file mode 100644 index 0000000000..1c8015bfc2 --- /dev/null +++ b/front_end/src/constants/chart_dash.ts @@ -0,0 +1,9 @@ +export const CHART_DASH = { + grid: "3 2", + cursor: "5 2", + quartile: "2 2", + threshold: "2 2", + timelineMarker: "4 3", +} as const; + +export type ChartDashKey = keyof typeof CHART_DASH; diff --git a/front_end/src/constants/chart_stroke.ts b/front_end/src/constants/chart_stroke.ts new file mode 100644 index 0000000000..b443eae2c8 --- /dev/null +++ b/front_end/src/constants/chart_stroke.ts @@ -0,0 +1,12 @@ +export const CHART_STROKE_WIDTH = { + forecastLine: 1.5, + resolutionDiamond: 2.5, + grid: 1, + cursor: 1, +} as const; + +export const CHART_POINT_SIZE = { + resolutionDiamond: 10, + userPoint: 6, + cursor: 4, +} as const; diff --git a/front_end/src/constants/chart_theme.ts b/front_end/src/constants/chart_theme.ts index aa21ed2b8c..e15280ed05 100644 --- a/front_end/src/constants/chart_theme.ts +++ b/front_end/src/constants/chart_theme.ts @@ -1,10 +1,12 @@ import { merge } from "lodash"; import { VictoryTheme, VictoryThemeDefinition } from "victory"; +import { + CHART_FONT_FAMILY, + CHART_FONT_SIZE, +} from "@/constants/chart_typography"; import { METAC_COLORS } from "@/constants/colors"; -const sansSerif = "var(--font-inter-variable) var(--font-inter)"; - type TickSizeFn = (args: { text?: string }) => number; const dynamicTickSize: TickSizeFn = ({ text }) => (text === "" ? 3 : 5); @@ -29,8 +31,17 @@ export const baseChartTheme: VictoryThemeDefinition = { ticks: { size: dynamicTickSize as unknown as number, }, - tickLabels: { fontFamily: sansSerif, fontSize: 9, padding: 0 }, - axisLabel: { fontFamily: sansSerif, fontSize: 9 }, + tickLabels: { + fontFamily: CHART_FONT_FAMILY, + fontSize: CHART_FONT_SIZE.tick, + fontVariantNumeric: "tabular-nums", + padding: 0, + }, + axisLabel: { + fontFamily: CHART_FONT_FAMILY, + fontSize: CHART_FONT_SIZE.axisLabel, + fontVariantNumeric: "tabular-nums", + }, }, }, }; diff --git a/front_end/src/constants/chart_tokens.ts b/front_end/src/constants/chart_tokens.ts new file mode 100644 index 0000000000..3dfe4d3bb6 --- /dev/null +++ b/front_end/src/constants/chart_tokens.ts @@ -0,0 +1,28 @@ +import { CHART_DASH } from "./chart_dash"; +import { CHART_POINT_SIZE, CHART_STROKE_WIDTH } from "./chart_stroke"; +import { CHART_FONT_STYLE } from "./chart_typography"; + +export type ChartThemeOverride = { + typography?: Partial; + dash?: Partial; + stroke?: Partial; + point?: Partial; +}; + +export type ResolvedChartTokens = { + typography: typeof CHART_FONT_STYLE; + dash: typeof CHART_DASH; + stroke: typeof CHART_STROKE_WIDTH; + point: typeof CHART_POINT_SIZE; +}; + +export function resolveChartTokens( + override?: ChartThemeOverride +): ResolvedChartTokens { + return { + typography: { ...CHART_FONT_STYLE, ...override?.typography }, + dash: { ...CHART_DASH, ...override?.dash }, + stroke: { ...CHART_STROKE_WIDTH, ...override?.stroke }, + point: { ...CHART_POINT_SIZE, ...override?.point }, + }; +} diff --git a/front_end/src/constants/chart_typography.ts b/front_end/src/constants/chart_typography.ts new file mode 100644 index 0000000000..b19b1454c5 --- /dev/null +++ b/front_end/src/constants/chart_typography.ts @@ -0,0 +1,33 @@ +export const CHART_FONT_FAMILY = "Inter, sans-serif"; + +export const CHART_FONT_SIZE = { + tick: 10, + axisLabel: 11, + cursor: 10, + tooltip: 12, +} as const; + +const tabularNums = "tabular-nums" as const; + +export const CHART_FONT_STYLE = { + tick: { + fontFamily: CHART_FONT_FAMILY, + fontSize: CHART_FONT_SIZE.tick, + fontVariantNumeric: tabularNums, + }, + axisLabel: { + fontFamily: CHART_FONT_FAMILY, + fontSize: CHART_FONT_SIZE.axisLabel, + fontVariantNumeric: tabularNums, + }, + cursor: { + fontFamily: CHART_FONT_FAMILY, + fontSize: CHART_FONT_SIZE.cursor, + fontVariantNumeric: tabularNums, + }, + tooltip: { + fontFamily: CHART_FONT_FAMILY, + fontSize: CHART_FONT_SIZE.tooltip, + fontVariantNumeric: tabularNums, + }, +} as const; diff --git a/front_end/src/utils/svg_export.ts b/front_end/src/utils/svg_export.ts index 92bc5557e9..6844c442a8 100644 --- a/front_end/src/utils/svg_export.ts +++ b/front_end/src/utils/svg_export.ts @@ -3,19 +3,26 @@ const STYLE_PROPERTIES = [ "stroke", "stroke-width", "stroke-dasharray", + "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", + "stroke-miterlimit", "font-family", "font-size", "font-weight", "font-style", + "font-variant-numeric", + "letter-spacing", "opacity", "fill-opacity", "stroke-opacity", "text-anchor", "dominant-baseline", + "alignment-baseline", + "paint-order", "text-decoration", "display", + "visibility", "clip-path", ];