import styles from "./StatCard.module.css";
/**
* ◎○△×のような判定色ではなく KPI の意味合い(成功/警告/失敗/参考値)を表す色分け。
* `color` ではなく `tone` という名前にしているのは、呼び出し側が生の色コードを
* 直書きできないようにするため(CLAUDE.md §9: 色はテーマ変数経由で指定する)。
*
* ★`mt`(中立)★: 良し悪しを示さない数(例: ダッシュボードの「結果待ち」。D-173)。
* 新しい色は足さず、既存の控えめな文字色(`--tx-m` / `--tx-d`)だけを使う。
*/
export type StatTone = "ok" | "wn" | "ng" | "ac" | "mt";
interface StatCardProps {
/** 表示する値。数値の文字列化・丸めは呼び出し側(lib/judge の displayRate 等)の責務 */
value: string;
label: string;
sub?: string;
tone: StatTone;
onClick?: () => void;
}
/**
* モックの Num 相当の統計カード。
* ダッシュボード(F-01)と レポート(F-04)の KPI 4列で共用するため、
* 画面固有のロジック(何のカードか等)は持たせない。
* ★押せるカードはキーボードでも押せる(role="button"・Tab・Enter は keydown / Space は keyup。指示書BC 5-4)★ —
* `<button>` にしないのは、中の `<div>` が button の中に置けない要素で、CSS も変わるため。
*/
export function StatCard({ value, label, sub, tone, onClick }: StatCardProps) {
return (
<div
className={`${styles.card} ${styles[tone]} ${onClick ? styles.clickable : ""}`}
onClick={onClick}
role={onClick ? "button" : undefined}
tabIndex={onClick ? 0 : undefined}
// ★ARIA の button の作法★ — Enter は押した時(keydown。押しっぱなしの繰り返しは無視)、
// Space は離した時(keyup)に押す。Space の keydown では既定(ページのスクロール)だけ止める
onKeyDown={
onClick
? (e) => {
if (e.key === "Enter") {
e.preventDefault();
if (!e.repeat) onClick();
} else if (e.key === " ") {
e.preventDefault();
}
}
: undefined
}
onKeyUp={
onClick
? (e) => {
if (e.key === " ") {
e.preventDefault();
onClick();
}
}
: undefined
}
>
<div className={styles.label}>{label}</div>
<div className={styles.value}>{value}</div>
{sub && <div className={styles.sub}>{sub}</div>}
</div>
);
}