Energy Arc Card
Summarises how a session's energy moved: a score, an interpretive badge, a sparkline, and four contributing metrics.
When to Use
Variants
Canonical (light)
The default. Four regions: eyebrow header, score row, sparkline with axis labels, and a 2×2 metric grid.
<?= ws_energy_arc_card([
'eyebrow' => 'Energy Arc',
'timeUsed' => '8 of 8h used',
'status' => ['text' => 'Complete', 'type' => 'success'],
'score' => 82,
'scoreBadge' => ['text' => 'Needs Work', 'type' => 'warning'],
'chartData' => [['time' => '9:00', 'value' => 48], /* … */],
'timeLabels' => ['9:00', '10:30', '1:00', '5:00'],
'metrics' => [
['label' => 'Pacing', 'value' => '~17m', 'fill' => 30],
['label' => 'Engagement', 'value' => '63%', 'fill' => 63],
],
]) ?>Dark
For presentation mode and dark dashboards. Badges and bars switch to a tinted-on-dark treatment.
<?= ws_energy_arc_card([/* … */ 'theme' => 'dark']) ?>
Score tiers
The badge does the interpreting. Drive its type from the score so colour reinforces the number: 85+ success, 70+ info, 50+ warning, below 50 danger.
States
| State | Behavior |
|---|---|
| Default | Static. The card reports; nothing in it is interactive. |
| Score clamped | Values below 0 become 0, above scoreMax become scoreMax. A bad score can't overflow the row. |
| Header hidden | showHeader => false drops the eyebrow row so a container can supply its own title. This is what Planner Inspector Rail sets automatically. |
| Badge variant | scoreBadge.variant is pill by default; note gives the smaller mono tag the inspector rail uses. |
| Too few chart points | Fewer than four points renders a near-flat line that reads as no data. Pass four to eight; beyond ten the arc loses definition at this width. |
| No chart data | The chart region renders empty. Guard on the array and show Empty State instead. |
Real-World Usage
The Coach retrospective header. The badge tier is derived from the score rather than hand-set, so the colour can never contradict the number.
<?php
$score = $energyScorer->score($planId);
$tier = match (true) {
$score >= 85 => ['Excellent', 'success'],
$score >= 70 => ['On Track', 'info'],
$score >= 50 => ['Needs Work', 'warning'],
default => ['At Risk', 'danger'],
};
?>
<?= ws_energy_arc_card([
'eyebrow' => 'Energy Arc',
'timeUsed' => formatDuration($used) . ' of ' . formatDuration($planned) . ' used',
'status' => ['text' => $session['status_label'], 'type' => $session['status_type']],
'score' => $score,
'scoreBadge' => ['text' => $tier[0], 'type' => $tier[1]],
'chartData' => $energyScorer->series($planId), // 4–8 points
'timeLabels' => $energyScorer->axisLabels($planId),
'metrics' => $energyScorer->dimensions($planId), // up to 4
]) ?>Options
| Option | Type | Default | Purpose |
|---|---|---|---|
score | int | 0 | Effectively required. Clamped to 0–scoreMax. |
scoreMax | int | 100 | Denominator shown beside the score |
scoreBadge | array | null | ['text' => …, 'type' => …, 'variant' => …]. Types: success | warning | danger | info | neutral. variant is pill (default) or note. |
eyebrow | string | 'Energy Arc' | Top-left label, rendered uppercase |
timeUsed | string | '' | Muted progress text in the header |
status | array | null | ['text' => …, 'type' => …], same types as the badge |
showHeader | bool | true | Render the eyebrow row. Undocumented in the helper's docblock, but supported — the inspector rail relies on it. |
chartData | array | [] | [['time' => …, 'value' => 0..100]]. Values are clamped. |
timeLabels | array | [] | X-axis tick strings, spaced evenly. Independent of chartData — they don't have to match point-for-point. |
metrics | array | [] | Up to 4: ['label', 'value', 'fill' => 0..100, 'barColor'?]. Keep values to 3–5 characters. |
theme | string | 'light' | light | dark. Corrected: this page previously documented the default as dark; the template defaults to light. |
accent | string | theme default | Overrides the accent as an inline CSS variable. Pass a token reference, not a literal hex. |
id / class / attrs | string / string / array | — | Standard passthrough |
Accessibility
| Concern | Behavior |
|---|---|
| Chart | The sparkline carries role="img" with aria-label="Energy arc over time", so it's announced as one graphic rather than a pile of SVG nodes. Good — but the label is generic and conveys no shape or trend. |
| Decorative parts | Grid lines and the axis carry aria-hidden="true". |
| Score | Score and denominator are adjacent text, so "82 out of 100" is announced in order without extra wiring. |
| Metrics | Label and value are text; the bar is presentational. The number carries the meaning, so the fill is safe reinforcement. |
| Keyboard | Nothing is focusable, which is correct for a read-only summary. |
| Colour independence | The badge text names the tier — "At Risk", not just red. Keep it that way; the tier must never live in colour alone. |
| Data alternative | Worth improving: the trend itself is only available visually. Consider extending the chart's aria-label to describe the shape — "rises to a peak mid-morning, dips after lunch, recovers by close" — or offering the series as a table. |
| Contrast | Light and dark themes each pair tested foreground and background. A custom accent bypasses that — verify it against both themes if the card appears in each. |
Tokens
The card resolves a theme-scoped accent and surface set on its root, so the light and dark treatments share one set of internal rules. The accent is overridable through the accent option, which writes an inline CSS variable.
| Token group | Used for |
|---|---|
| Accent | Chart line, metric bar fills, and score emphasis. Theme-derived unless overridden. |
| Surface and border | Card background and edge, swapped per theme |
| Ink scale | Score, labels, metric values, and the muted header text |
| Status colours | The five badge and status types — success, warning, danger, info, neutral |
| Type scale | Display score, mono eyebrow, caption-size metric labels |
See the .ws-energy-arc rules in components.css for the exact declarations, and Token Reference for current values.
CSS Classes
| Class | Purpose |
|---|---|
.ws-energy-arc | Root container |
.ws-energy-arc--dark | Dark theme. The light theme's modifier is emitted but has no rule — light is the base styling. |
.ws-energy-arc__card | Inner card surface |
.ws-energy-arc__header / __eyebrow | Top row, suppressed by showHeader: false |
.ws-energy-arc__status (+ --success / --warning / --danger / --info) | Header status chip |
.ws-energy-arc__score-row / __score / __score-value / __score-max | Score display |
.ws-energy-arc__badge (+ type modifiers, plus --note) | Interpretive badge and its two variants |
.ws-energy-arc__chart / __axis | Sparkline and its tick labels |
.ws-energy-arc__metrics / __metric | The 2×2 grid and its cells |
.ws-energy-arc__metric-label / -value / -bar / -bar-fill | Metric internals |
Files
| File | Purpose |
|---|---|
includes/components/helpers.php | ws_energy_arc_card() helper function |
includes/components/energy-arc-card.php | Template — clamping, theme resolution, chart and metric markup |
includes/components/components.css | Styles (.ws-energy-arc rules) |
includes/components/planner-inspector-rail.php | Wraps this card with showHeader: false |