Files
school_compare/nextjs-app/components/DeltaChip.tsx
T

58 lines
1.6 KiB
TypeScript
Raw Normal View History

/**
* 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>
);
}