58 lines
1.6 KiB
TypeScript
58 lines
1.6 KiB
TypeScript
|
|
/**
|
||
|
|
* DeltaChip — small coloured chip showing how a value compares to a baseline.
|
||
|
|
*
|
||
|
|
* Example: <DeltaChip value={70} baseline={60} unit="pts" /> → "+10 pts"
|
||
|
|
*
|
||
|
|
* Colours (reuse globals.css status tokens):
|
||
|
|
* above baseline → statusGood (teal)
|
||
|
|
* below baseline → statusBad (coral)
|
||
|
|
* within ±tolerance → statusWarn (gold, "in line")
|
||
|
|
*/
|
||
|
|
|
||
|
|
import styles from './DeltaChip.module.css';
|
||
|
|
|
||
|
|
interface DeltaChipProps {
|
||
|
|
value: number | null | undefined;
|
||
|
|
baseline: number | null | undefined;
|
||
|
|
/** Unit suffix for the delta (e.g. "pts", "%") */
|
||
|
|
unit?: string;
|
||
|
|
/** Absolute delta below which the chip is treated as neutral */
|
||
|
|
tolerance?: number;
|
||
|
|
/** Override label when we want "vs national" under a number */
|
||
|
|
suffix?: string;
|
||
|
|
/** Smaller variant for inline use next to metric values */
|
||
|
|
size?: 'sm' | 'md';
|
||
|
|
}
|
||
|
|
|
||
|
|
export function DeltaChip({
|
||
|
|
value,
|
||
|
|
baseline,
|
||
|
|
unit = 'pts',
|
||
|
|
tolerance = 1,
|
||
|
|
suffix,
|
||
|
|
size = 'md',
|
||
|
|
}: DeltaChipProps) {
|
||
|
|
if (value == null || baseline == null) return null;
|
||
|
|
|
||
|
|
const delta = value - baseline;
|
||
|
|
const rounded = Math.round(delta);
|
||
|
|
|
||
|
|
let tone: 'good' | 'bad' | 'neutral';
|
||
|
|
if (Math.abs(delta) < tolerance) tone = 'neutral';
|
||
|
|
else if (delta > 0) tone = 'good';
|
||
|
|
else tone = 'bad';
|
||
|
|
|
||
|
|
const toneClass =
|
||
|
|
tone === 'good' ? styles.good : tone === 'bad' ? styles.bad : styles.neutral;
|
||
|
|
|
||
|
|
const sign = rounded > 0 ? '+' : '';
|
||
|
|
const label = `${sign}${rounded} ${unit}`.trim();
|
||
|
|
|
||
|
|
return (
|
||
|
|
<span className={`${styles.chip} ${toneClass} ${size === 'sm' ? styles.sm : ''}`}>
|
||
|
|
{label}
|
||
|
|
{suffix && <span className={styles.suffix}>{suffix}</span>}
|
||
|
|
</span>
|
||
|
|
);
|
||
|
|
}
|