mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
fix(insights): point derived score-band tokens at the AA-corrected semantic colours
The band primitives (score ring, coverage dots, contributor bars, provenance chips + standard link, sparkline tint, trend arrow/delta) painted straight from the raw `--dracula-*` variables, which carry no `:root.light` override. On the white card the Alucard light theme uses, the green/orange/yellow cleared roughly 1.1-1.5:1 — under AA — and the `bg-dracula-yellow` confidence dot read near-invisible. The file comment claimed they 'track automatically'; they did not. Point BAND_NUMBER/PROGRESS/BORDER/VAR, the coverage-meter dot tint, the provenance cyan chips, the sparkline stroke, and sentimentColorClass at the semantic `--success`/`--warning`/`--destructive`/`--info` tokens instead. Those alias the same Dracula tones in dark mode (pixel-identical there, the primary target) but carry the darker AA-safe values under `:root.light`. Clamp the score-ring provisional caption to one line so a longer localised string cannot wrap over the ring arc.
This commit is contained in:
1 parent
ecf93317dd
commit
60c0ba4483
6 files changed
+54
-29
No files matched your search
@@ -5,44 +5,54 @@
|
||||
* exact same band colour grammar the shipped `health-score-card` already
|
||||
* uses, without each component redeclaring the map (concept cohesion).
|
||||
*
|
||||
* No new tokens — these point at the existing `--dracula-*` variables in
|
||||
* `globals.css`. A green/yellow/red band is the one semantic the whole
|
||||
* v1.10 score language extends.
|
||||
* These point at the *semantic* feedback tokens (`--success` / `--warning`
|
||||
* / `--destructive`), NOT the raw `--dracula-*` primitives. That matters
|
||||
* for contrast: `:root.light` (Alucard) overrides the semantic tokens to
|
||||
* AA-safe darker tones (`--success: #14720a`, `--warning: #a34d14`,
|
||||
* `--destructive: #cb3a2a`) precisely because straight Dracula
|
||||
* green/orange on a white `--card` clears only ~1.1–1.5:1 — under AA.
|
||||
* Painting the band off the semantic token means every score surface
|
||||
* tracks that light-mode correction automatically, in both themes; the
|
||||
* raw `--dracula-*` primitives do NOT carry a light override. A
|
||||
* green/yellow/red band is the one semantic the whole v1.10 score
|
||||
* language extends.
|
||||
*/
|
||||
|
||||
export type ScoreBand = "green" | "yellow" | "red";
|
||||
|
||||
/** Tailwind text-colour class per band (the headline number colour). */
|
||||
export const BAND_NUMBER_CLASS: Record<ScoreBand, string> = {
|
||||
green: "text-dracula-green",
|
||||
yellow: "text-dracula-orange",
|
||||
red: "text-dracula-red",
|
||||
green: "text-success",
|
||||
yellow: "text-warning",
|
||||
red: "text-destructive",
|
||||
};
|
||||
|
||||
/** Tailwind background class per band (progress/fill bars). */
|
||||
export const BAND_PROGRESS_CLASS: Record<ScoreBand, string> = {
|
||||
green: "bg-dracula-green",
|
||||
yellow: "bg-dracula-orange",
|
||||
red: "bg-dracula-red",
|
||||
green: "bg-success",
|
||||
yellow: "bg-warning",
|
||||
red: "bg-destructive",
|
||||
};
|
||||
|
||||
/** Tailwind border-colour class per band (card / chip outlines). */
|
||||
export const BAND_BORDER_CLASS: Record<ScoreBand, string> = {
|
||||
green: "border-dracula-green/40",
|
||||
yellow: "border-dracula-orange/40",
|
||||
red: "border-dracula-red/40",
|
||||
green: "border-success/40",
|
||||
yellow: "border-warning/40",
|
||||
red: "border-destructive/40",
|
||||
};
|
||||
|
||||
/**
|
||||
* The raw CSS variable per band — used where a Recharts `fill` needs an
|
||||
* actual colour string rather than a Tailwind class (the score ring's
|
||||
* `<RadialBar fill>`). Reads the same `--dracula-*` tokens so dark and
|
||||
* Alucard light modes track automatically.
|
||||
* `<RadialBar fill>`). Reads the semantic tokens so dark and Alucard light
|
||||
* modes track the AA-safe light overrides automatically (the
|
||||
* `--dracula-*` primitives carry no light override and would fail AA on
|
||||
* the white card).
|
||||
*/
|
||||
export const BAND_VAR: Record<ScoreBand, string> = {
|
||||
green: "var(--dracula-green)",
|
||||
yellow: "var(--dracula-orange)",
|
||||
red: "var(--dracula-red)",
|
||||
green: "var(--success)",
|
||||
yellow: "var(--warning)",
|
||||
red: "var(--destructive)",
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,12 +48,21 @@ export interface CoverageMeterProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/** Dot tint per confidence band — reuses the existing dracula vocabulary. */
|
||||
/**
|
||||
* Dot tint per confidence band. Points at the *semantic* feedback tokens
|
||||
* (`--success` / `--warning` / `--destructive`), not the raw `--dracula-*`
|
||||
* primitives, so the dots track the AA-safe `:root.light` overrides on the
|
||||
* white card — straight `bg-dracula-yellow` cleared barely 1.1:1 on white
|
||||
* and read near-invisible. The four bands collapse onto the three semantic
|
||||
* severities (medium + low both ride the caution `--warning`); the lit-dot
|
||||
* count + the percent label carry the medium↔low distinction, never colour
|
||||
* alone.
|
||||
*/
|
||||
const BAND_DOT_CLASS: Record<DerivedConfidenceBand, string> = {
|
||||
high: "bg-dracula-green",
|
||||
medium: "bg-dracula-yellow",
|
||||
low: "bg-dracula-orange",
|
||||
draft: "bg-dracula-red",
|
||||
high: "bg-success",
|
||||
medium: "bg-warning",
|
||||
low: "bg-warning",
|
||||
draft: "bg-destructive",
|
||||
};
|
||||
|
||||
function clampInt(value: number, min: number, max: number): number {
|
||||
|
||||
@@ -100,7 +100,7 @@ export function ProvenanceExplainer({
|
||||
<li
|
||||
key={input}
|
||||
data-slot="provenance-explainer-input-chip"
|
||||
className="border-dracula-cyan/30 text-dracula-cyan/90 inline-flex items-center rounded-full border bg-transparent px-1.5 py-0.5 text-[10px] leading-none"
|
||||
className="border-info/40 text-info inline-flex items-center rounded-full border bg-transparent px-1.5 py-0.5 text-[10px] leading-none"
|
||||
>
|
||||
{input}
|
||||
</li>
|
||||
@@ -141,7 +141,7 @@ export function ProvenanceExplainer({
|
||||
href={standard.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-dracula-cyan hover:text-dracula-cyan/80 focus-visible:ring-ring/50 inline-flex items-center gap-1 rounded text-[11px] font-medium focus-visible:ring-2 focus-visible:outline-none"
|
||||
className="text-info hover:text-info/80 focus-visible:ring-ring/50 inline-flex items-center gap-1 rounded text-[11px] font-medium focus-visible:ring-2 focus-visible:outline-none"
|
||||
>
|
||||
{t("insights.derived.provenance.standardLink", {
|
||||
name: standard.name,
|
||||
|
||||
@@ -188,7 +188,7 @@ export function ScoreRing({
|
||||
{!hasScore && (
|
||||
<span
|
||||
data-slot="score-ring-provisional"
|
||||
className="text-muted-foreground absolute inset-x-0 bottom-0 text-center text-[10px] leading-tight"
|
||||
className="text-muted-foreground absolute inset-x-0 bottom-0 line-clamp-1 px-1 text-center text-[10px] leading-tight"
|
||||
>
|
||||
{t("insights.derived.scoreRing.provisionalCaption")}
|
||||
</span>
|
||||
|
||||
@@ -94,11 +94,13 @@ export function SparklineDeltaTile({
|
||||
|
||||
// The sparkline tints with the trend sentiment so it reads "same signal"
|
||||
// as the arrow; neutral metrics ride the muted-foreground line.
|
||||
// Semantic tokens, not raw --dracula-*, so the sparkline tint tracks the
|
||||
// AA-safe :root.light overrides on the white card (the band-token fix).
|
||||
const strokeVar =
|
||||
arrowSentiment === "positive"
|
||||
? "var(--dracula-green)"
|
||||
? "var(--success)"
|
||||
: arrowSentiment === "negative"
|
||||
? "var(--dracula-orange)"
|
||||
? "var(--warning)"
|
||||
: "var(--muted-foreground)";
|
||||
const fillId = `spark-${label.replace(/[^a-zA-Z0-9]/g, "")}`;
|
||||
|
||||
|
||||
@@ -44,8 +44,12 @@ export function getTrendSentiment(
|
||||
export function sentimentColorClass(
|
||||
direction: TrendSentimentDirection,
|
||||
): string {
|
||||
if (direction === "positive") return "text-dracula-green";
|
||||
if (direction === "negative") return "text-dracula-orange";
|
||||
// Semantic tokens, not raw --dracula-*: `--success` / `--warning` alias
|
||||
// the same Dracula green/orange in dark mode (pixel-identical there) but
|
||||
// carry the AA-safe `:root.light` overrides, so the trend arrow + delta
|
||||
// clear AA on the white card instead of the ~1.2:1 the raw primitives hit.
|
||||
if (direction === "positive") return "text-success";
|
||||
if (direction === "negative") return "text-warning";
|
||||
return "text-muted-foreground";
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user