Trend Chart Component#

Overview#

The Trend Chart component visualizes performance data over multiple years, allowing stakeholders to see long-term patterns and assess whether improvements are sustained or temporary.

Purpose#

To provide a clear, accessible visualization of multi-year performance trends that helps stakeholders understand whether schools are making consistent progress toward their goals.

Component Structure#

The component displays a line chart or bar chart showing performance over time:

English Language Arts - 5 Year Trend
─────────────────────────────────────────────────────
70% │                                        ●
    │                                   ●
60% │                              ●
    │                         ●
50% │                    ●
    │
40% │
    └─────────────────────────────────────────────
      2020   2021   2022   2023   2024

● 2020: 50.2% (Yellow)
● 2021: 52.8% (Yellow)
● 2022: 58.3% (Yellow)
● 2023: 62.1% (Green)
● 2024: 65.5% (Green)

Chart Types#

Line Chart (Default): - Best for showing continuous trends - Emphasizes direction of change - Good for comparing multiple groups on same chart

Bar Chart: - Best for comparing discrete years - Easier to read exact values - Good for showing status level colors

Area Chart: - Shows cumulative progress - Emphasizes magnitude of change - Good for goal attainment visualization

Props / Attributes#

interface TrendChartProps {
  metricName: string;
  chartType?: 'line' | 'bar' | 'area'; // Default: 'line'
  data: YearlyPerformanceData[];
  showStatusColors?: boolean; // Color points by status level
  showGoalLine?: boolean; // Display target goal
  goalValue?: number;
  height?: number; // Default: 300
  width?: number | 'auto'; // Default: 'auto'
  interactive?: boolean; // Enable tooltips and zoom
  ariaLabel?: string;
}

interface YearlyPerformanceData {
  year: number;
  value: number;
  statusLevel?: StatusLevel;
  studentCount?: number;
  dataSuppressed?: boolean;
}

Accessibility Features#

  • Keyboard Navigation: Arrow keys to navigate data points

  • Screen Reader Support: Complete data table alternative

  • ARIA Labels: Descriptive labels for all chart elements

  • Tooltip Announcements: Screen readers announce on focus

  • High Contrast Mode: Patterns in addition to colors

Data Table Alternative#

The component provides a data table for screen readers and as a fallback:

<div class="trend-chart">
  <svg class="trend-chart__visual" aria-hidden="true">
    <!-- Chart visualization -->
  </svg>

  <table class="trend-chart__data sr-only">
    <caption>English Language Arts Performance 2020-2024</caption>
    <thead>
      <tr>
        <th scope="col">Year</th>
        <th scope="col">Percentage Meeting Standard</th>
        <th scope="col">Status Level</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">2020</th>
        <td>50.2%</td>
        <td>Yellow (Medium)</td>
      </tr>
      <!-- More rows -->
    </tbody>
  </table>
</div>

Interactive Features#

Tooltips: Hover/focus on data points to see details

2024: 65.5% Meeting Standard
Status: Green (High)
Change from 2023: +3.4 percentage points
Students: 500

Zoom: Click and drag to zoom into specific time period

Compare: Toggle visibility of different student groups

Export: Download chart as PNG or SVG, data as CSV

Visual Design Guidelines#

Color Palette:

.trend-chart {
  --line-color: #1976D2;
  --point-color: #1565C0;
  --grid-color: #E0E0E0;
  --goal-line-color: #4CAF50;
  --axis-color: #424242;
}

Typography: - Axis labels: 12px, semibold - Data labels: 11px, regular - Title: 16px, bold

Spacing: - Padding: 20px - Point radius: 5px - Line width: 2px

Usage Example#

import { TrendChart } from '@/components/performance';

export function PerformanceDetail() {
  const trendData = [
    { year: 2020, value: 50.2, statusLevel: { level: 'yellow' }, studentCount: 480 },
    { year: 2021, value: 52.8, statusLevel: { level: 'yellow' }, studentCount: 490 },
    { year: 2022, value: 58.3, statusLevel: { level: 'yellow' }, studentCount: 495 },
    { year: 2023, value: 62.1, statusLevel: { level: 'green' }, studentCount: 505 },
    { year: 2024, value: 65.5, statusLevel: { level: 'green' }, studentCount: 500 },
  ];

  return (
    <div className="performance-detail">
      <h2>English Language Arts Trend</h2>
      <TrendChart
        metricName="English Language Arts"
        data={trendData}
        showStatusColors={true}
        showGoalLine={true}
        goalValue={70}
        interactive={true}
        ariaLabel="Five year trend showing English Language Arts performance improving from 50.2% in 2020 to 65.5% in 2024"
      />
    </div>
  );
}

Handling Missing Data#

When data is missing for specific years:

  • Gap in Line: Show dotted line between available points

  • Annotation: Add note explaining gap (e.g., “No testing in 2021 due to COVID-19”)

  • Screen Reader: Announce missing years in data table

Technical Implementation#

The component uses D3.js for rendering:

import * as d3 from 'd3';

const drawLineChart = (data: YearlyPerformanceData[], config: ChartConfig) => {
  const svg = d3.select(containerRef.current);

  const xScale = d3.scaleLinear()
    .domain([d3.min(data, d => d.year), d3.max(data, d => d.year)])
    .range([0, width]);

  const yScale = d3.scaleLinear()
    .domain([0, 100])
    .range([height, 0]);

  const line = d3.line<YearlyPerformanceData>()
    .x(d => xScale(d.year))
    .y(d => yScale(d.value))
    .curve(d3.curveMonotoneX);

  svg.append('path')
    .datum(data)
    .attr('d', line)
    .attr('stroke', config.lineColor)
    .attr('fill', 'none');
};

See Also#