Skip to content
SuperCoach

Components · Data display

Chart

Beta

Charts using the chart palette, such as weekly volume.

Completed workouts per week, all clients

Up from 42 in week 1 to 61 in week 6, with a dip in week 4.

Show data table
WeekCompleted workouts
Week 142
Week 248
Week 351
Week 447
Week 555
Week 661

When to use

  • To show a trend or a comparison that a number alone can't: completed workouts per week, revenue per month, check-in rate by program.
  • On dashboards and reports, next to the number the chart explains.

When not to use

  • For one number: show it large, in a Card, with the change in text ("+12% on last month").
  • When coaches need exact values to act on, such as invoices: use a Table or Data table.
  • For more than five series: group the rest as "Other", or split the chart.
  • For progress toward one goal: use Progress.

Anatomy

The Chart component is shadcn's thin wrapper around Recharts (3.8, installed). ChartContainer maps each series in a ChartConfig to a CSS variable (--color-workouts), sizes the chart and styles axes, grid and cursor with tokens. ChartTooltipContent and ChartLegendContent are styled tooltip and legend contents. The chart itself is plain Recharts: BarChart, LineChart, XAxis, Bar.

Completed workouts per week

Up from 42 to 51, with a dip in week 4.

Completed workouts

Show data table

  1. 1. Title: what is measured, over what period
  2. 2. Summary: one sentence with the takeaway
  3. 3. Legend with text, in palette order
  4. 4. Plot: axes, gridlines and marks, always left to right
  5. 5. Text alternative: a data table

Variants

The default above is a bar chart: one bar per period, for counts. A line chart shows a trend over time, here with two series.

Monthly revenue in SAR, May to October 2026

Subscriptions grew every month, from SAR 12,400 to SAR 16,950. One-off programs stayed between SAR 1,800 and SAR 3,100.

  • Subscriptions
  • One-off programs
Show data table
MonthSubscriptionsOne-off programs
MaySAR 12,400SAR 2,100
JunSAR 13,100SAR 1,800
JulSAR 13,900SAR 2,600
AugSAR 14,600SAR 2,200
SepSAR 15,800SAR 3,100
OctSAR 16,950SAR 2,900
ChartUse for
BarCounts per period or per category: workouts per week, clients per program. Bars start at zero.
LineA trend over time with many points: revenue, body weight, check-in rate.
Stacked barParts of a total per period, with up to three parts.

Every chart uses the theme's chart palette, var(--chart-1) to var(--chart-5), in that order. Put the colors in the ChartConfig as CSS variables, never as hex, so the chart follows SuperCoach and Coach:

const config = {
  subscriptions: { label: "Subscriptions", color: "var(--chart-1)" },
  programs: { label: "One-off programs", color: "var(--chart-2)" },
} satisfies ChartConfig;

Use the color key. The theme key is for light and dark values and stays unused until there is a dark theme (DECISIONS #13).

States

StateWhat changesToken
RestAxis labels muted, gridlines lightfill-muted-foreground, stroke-border/50
Hover or keyboard focus on a pointCursor band or line, tooltip with the valuesfill-muted, stroke-border; tooltip bg-background, border-border/50, shadow-xl
LoadingA Skeleton the size of the chart, with the title already shown—
No dataAn Empty state in place of the plot: "No workouts logged yet"—

Usage guidelines

  • Title first, in plain words: "Completed workouts per week, all clients".
  • Then one sentence with the takeaway, so coaches don't have to work it out: "Up from 42 in week 1 to 61 in week 6".
  • Bars start at zero. Lines may start elsewhere, but label the axis.
  • Use the palette in order; chart-1 is the main series. Don't use status colors for series; keep success and destructive for good and bad.
  • Don't animate on every data load. Recharts animates on mount; that is enough.

Monthly revenue in SAR, May to October 2026

Subscriptions grew every month, from SAR 12,400 to SAR 16,950.

Do.A title that names the measure and the period, and a sentence with the takeaway.

Revenue

Don't.A one-word title. Coaches can't tell the period, the currency or what changed.

Content guidelines

  • Titles say the measure, the unit and the period: "Monthly revenue in SAR, May to October 2026".
  • Axis labels are short: "Week 1", "Oct", "12k". Don't repeat the unit on every tick; put it in the title.
  • Legend labels match the column names in the data table.
  • Numbers use Western digits in both languages (QUESTIONS Q22). Amounts follow Content › Money: "SAR 12,400", "12400 ر.س".

Accessibility

KeyDoes
TabMoves focus to the chart (with accessibilityLayer)
Arrow left / Arrow rightMoves between data points and shows the tooltip for each
Tab or EscapeLeaves the chart
  • Name and summary. Wrap the chart in a <figure> with a <figcaption> title, and point aria-describedby at the summary sentence. Screen readers announce the title, then the summary.
  • accessibilityLayer. Set it on every Recharts chart. It makes the chart's SVG focusable (tabIndex="0", role="application") and lets the arrow keys step through the points, showing the tooltip for each. Recharts 3 turns it on by default; set it anyway so the intent is visible in code. Also pass the title to the chart's title prop: it becomes the SVG's <title>, so the focusable chart has a name ("Completed workouts per week, all clients, application").
  • Data table. A <details> with "Show data table" under the chart gives every value as text, in a real table with headers. It is the alternative for screen readers, for coaches with color vision deficiency, and for anyone who needs the exact number.
  • Legend with text. Every color has a label, and for two series the line style differs too (WCAG 1.4.1).
  • Contrast. Marks need 3:1 against the background; see the Q25 note above. Axis labels use muted-foreground (4.5:1 or more).

RTL

  • The plot does not mirror. Time runs left to right in both directions, so wrap the chart in dir="ltr", as the Data visualization foundation does. Recharts draws in fixed SVG coordinates; without the wrapper, the SVG text inherits right-to-left direction, which flips text-anchor, and the Y-axis labels slide into the plot.
  • Inside the wrapper the arrow keys keep their visual meaning: Arrow right moves to the next (later) point.
  • The title, summary, legend and data table follow the page direction: in Arabic the legend starts on the right.
  • Axis labels are in the reading language ("الأسبوع 1", "أكتوبر") with Western digits.

ChartTooltipContent formats values with Western digits in every locale (toLocaleString("en-US"), QUESTIONS Q22), so the tooltip matches the axis and the table. Upstream used the browser's locale, which showed Arabic-Indic digits on Arabic browsers.

Tokens used

Read from components/ui/chart.tsx at build time, so this list changes when the component does. Opacity modifiers such as /90 are shadcn hover and focus tints on top of the token.

Semantic color tokens used by this component
TokenUtilitiesSuperCoachCoach
--backgroundbg-backgroundwhitewhite
--borderstroke-border/50 stroke-border border-border/50neutral-200neutral-200
--foregroundtext-foregroundneutral-950neutral-950
--mutedfill-mutedneutral-100neutral-100
--muted-foregroundfill-muted-foreground text-muted-foregroundneutral-600neutral-600
  • Radiusrounded-lg
  • Radiusrounded-sm
  • Shadowshadow-xl
  • Typefont-medium
  • Typeleading-none
  • Typetext-xs

The series colors are not in this list because they come from the ChartConfig: --chart-1 to --chart-5, documented on Data visualization.

Props

<ChartContainer>

Also takes every prop of <div>

ChartContainer props
PropTypeDefault
configChartConfig—
childrenReact.ComponentProps< typeof RechartsPrimitive.ResponsiveContainer >["children"]—
initialDimension?{ width: number height: number }INITIAL_DIMENSION

<ChartTooltipContent>

Also takes every prop of <div>

ChartTooltipContent props
PropTypeDefault
hideLabel?booleanfalse
hideIndicator?booleanfalse
indicator?"line" | "dot" | "dashed""dot"
nameKey?string—
labelKey?string—

<ChartLegendContent>

Also takes every prop of <div>

ChartLegendContent props
PropTypeDefault
hideIcon?booleanfalse
nameKey?string—

Replaces in coach-admin

From the read-only audit of coach-admin: 63 style values, 78 uses.

coach-admin draws charts with Chart.js (src/components/Charts/Chart.js, and the Coach dashboards in src/GroupDashboard), with colors written in the chart options. Chart.js's own default colors are excluded from the audit. Moving to this component replaces those colors with the chart palette.

Classes and selectors

  • .chart-wrapper8
  • .chart-total4
  • .chart-card4
  • .chart-empty-state-icon4
  • .chart-sub-title-empty-state3
  • .chart-empty-state2
  • .chart-comparison-percentage-up2
  • .chart-sub-title2
  • .chart-comparison-percentage-down2
  • .chart-legend li, .bar-legend li, .line-legend li, .pie-lege2
  • .chart-comparison-percentage2
  • .chart-comparison-icon2

Files

  • src/components/Charts/Chart.js29
  • src/views/User/components/client-details/tabs-content/overview/charts/client-progress-chart.scss7
  • src/components/Charts/GetUserProgressChart.scss3

The inventory lists the first 12 locations of each value, so file counts are a lower bound.

Data visualization, Card, Table, Empty state, Color.