Hacktron Design System

TrendChart

A line or stacked-bar chart of values over time, with axes, tooltip and legend.

Use the Left and Right arrow keys to move between points. Escape hides the details.

<template>  <TrendChart    :data="chartData"    :series="[      { key: 'pr', label: 'PR review', color: 'var(--color-chart-chart-2)', value: (d) => d.pr },      { key: 'whitebox', label: 'Whitebox scan', color: 'var(--color-chart-chart-3)', value: (d) => d.whitebox },    ]"    type="bar"    :tick-format="formatTick"  /></template>

Props

Name Type Default
dataT[]-
seriesTrendChartSeries<T>[]-
type"line" | "bar""line"
heightnumber180
tickFormat(tick: number) => string-
yTickFormat(value: number) => string-
valueFormat(value: number) => stringString(value)
tooltipHeading(d: T) => string-
tooltipRowLabel(series: TrendChartSeries<T>, d: T) => string-
numTicksnumber7
yAxisPosition"left" | "right""left"
isLoadingbooleanfalse
errorbooleanfalse
errorLabelstring"Could not load this chart"
emptyLabelstring"No data for this period"
showLegendbooleanseries.length > 1
legendTotalsbooleanfalse
highlightedSeriesstring | nullnull
ariaLabelstring-
keyboardHintstring"Use the Left and Right arrow keys to move between points. Escape hides the details."

Guidelines

Do

  • Return null from a series' value accessor for "no data at this point" - a real 0 (0% SLA compliance, a zero-day MTTR) is a value, not an absence.
  • Pass ariaLabel (translated) so the plot has an accessible name and a keyboard path: Left/Right/Home/End step through the points and each point's rows are announced. Without it the plot is decorative, hidden from assistive tech and not focusable, and only the legend is read.
  • Set type="bar" for volumes/counts (scan volume, findings by day) and leave type="line" (the default) for rates and durations (SLA compliance, MTTR).
  • Pass tickFormat/tooltipHeading that match your data's own timezone semantics - a UTC-bucketed day needs a UTC formatter, not the ambient local-time one.
  • Pass tooltipHeading for the point's date: it renders once as the tooltip's heading, above one row per series, rather than on every row.
  • Set legendTotals when the count per series is the point of the chart (findings by severity); totals go through valueFormat.
  • To put the legend in the card header, pass :show-legend="false" and place a ChartLegend in Card's #header-actions, bound to the same ref as this chart's v-model:highlighted-series.
  • Pass error with a translated errorLabel when the query failed. It renders in the same frame as the empty state, with an error icon, and wins over the empty state.

Don't

  • Don't repeat an entry in data (the same object twice, or primitives): points are identified by reference, so hover dimming and the tooltip anchor resolve a repeat to its last occurrence. Build one object per point.
  • Don't feed type="bar" negative values: bars are for counts and volumes, and a value at or below zero draws no bar (it still counts toward the axis and shows in the tooltip). Return null for a missing point instead.
  • Don't pass a signed/pre-composed tooltip string as a series' label - pass the plain series name and let tooltipHeading supply the date as the tooltip's heading.
  • Don't reach for this to render a tiny inline sparkline with no axis/tooltip/legend - that is Sparkline, built for a MetricCard's #chart slot.