Risiko-Skala & Heatmap kontrastreicher auf Dunkel

- Score-Skala mit kräftigem Grün→Gelb→Orange→Rot-Verlauf statt blasser
  Pastelltöne; Marker Brutto weiß / Rest dunkel mit Kontrastring
- Heatmap-Zellen kräftigere Ampelfarben; R-Chips dunkel/weiß für Kontrast

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Martin
2026-07-03 09:44:36 +02:00
co-authored by Claude Opus 4.8
parent 7afd7f6acf
commit 9e54c7788f
3 changed files with 20 additions and 19 deletions
+1 -1
View File
@@ -178,7 +178,7 @@ export default async function RisksPage({
key={r.id} key={r.id}
href={`/risks?detail=${r.id}`} href={`/risks?detail=${r.id}`}
title={r.title} title={r.title}
className="rounded-md bg-[var(--elevated)] px-1.5 py-0.5 font-heading text-[10.5px] font-bold text-foreground shadow-sm hover:bg-[var(--elevated)]" className="rounded-md bg-[#0e1220]/75 px-1.5 py-0.5 font-heading text-[10.5px] font-bold text-white shadow-sm hover:bg-[#0e1220]"
> >
{riskRef(r.refNo)} {riskRef(r.refNo)}
</Link> </Link>
+9 -12
View File
@@ -20,7 +20,7 @@ import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { Modal } from "@/components/modal"; import { Modal } from "@/components/modal";
import { CiaBadge, CiaLegend, Pill, Tag } from "@/components/mockup-ui"; import { CiaBadge, CiaLegend, Pill, Tag } from "@/components/mockup-ui";
import { riskLevel, riskRef, RISK_PILL_TONE } from "@/lib/risk"; import { riskLevel, riskRef, RISK_PILL_TONE, RISK_SCALE_GRADIENT } from "@/lib/risk";
import { measureRef, MEASURE_STATUS_TONE } from "@/lib/measure"; import { measureRef, MEASURE_STATUS_TONE } from "@/lib/measure";
export type RiskWithDetail = Prisma.RiskGetPayload<{ export type RiskWithDetail = Prisma.RiskGetPayload<{
@@ -118,38 +118,35 @@ async function RatingCard({
); );
} }
/** Farbskala grün→rot mit Markern für Brutto (dunkel) und Rest (orange). SPEC §4.2. */ /** Kräftige Farbskala grün→rot mit Markern für Brutto (weiß) und Rest (dunkel). SPEC §4.2. */
function RiskScoreScale({ gross, residual }: { gross: number; residual: number | null }) { function RiskScoreScale({ gross, residual }: { gross: number; residual: number | null }) {
// 5×5 → Score 1..25; Position linear auf der Skala // 5×5 → Score 1..25; Position linear auf der Skala
const pos = (v: number) => `${((Math.min(25, Math.max(1, v)) - 1) / 24) * 100}%`; const pos = (v: number) => `${((Math.min(25, Math.max(1, v)) - 1) / 24) * 100}%`;
return ( return (
<div className="pt-1"> <div className="pt-1">
<div <div
className="relative h-3 rounded-lg" className="relative h-3.5 rounded-lg ring-1 ring-white/10"
style={{ style={{ background: RISK_SCALE_GRADIENT }}
background:
"linear-gradient(90deg,#dff3e5,#fdf0cf,#fbdcc0,#f6c3c1,#ef9a98)",
}}
> >
<span <span
className="absolute -top-1 h-5 w-[3px] -translate-x-1/2 rounded-sm bg-[#2b2646]" className="absolute -top-1.5 h-6.5 w-[4px] -translate-x-1/2 rounded-sm bg-white shadow-[0_0_0_1px_rgba(0,0,0,0.5)]"
style={{ left: pos(gross) }} style={{ left: pos(gross) }}
title={`Brutto ${gross}`} title={`Brutto ${gross}`}
/> />
{residual != null && ( {residual != null && (
<span <span
className="absolute -top-1 h-5 w-[3px] -translate-x-1/2 rounded-sm bg-[#e0982e]" className="absolute -top-1.5 h-6.5 w-[4px] -translate-x-1/2 rounded-sm bg-[#0e1220] shadow-[0_0_0_1px_rgba(255,255,255,0.7)]"
style={{ left: pos(residual) }} style={{ left: pos(residual) }}
title={`Rest ${residual}`} title={`Rest ${residual}`}
/> />
)} )}
</div> </div>
<div className="mt-1.5 flex items-center gap-4 text-[11px] text-muted-foreground"> <div className="mt-2 flex items-center gap-4 text-[11px] text-muted-foreground">
<span className="inline-flex items-center gap-1.5"> <span className="inline-flex items-center gap-1.5">
<i className="inline-block h-3 w-[3px] rounded-sm bg-[#2b2646]" /> Brutto <i className="inline-block h-3 w-[4px] rounded-sm bg-white ring-1 ring-black/40" /> Brutto
</span> </span>
<span className="inline-flex items-center gap-1.5"> <span className="inline-flex items-center gap-1.5">
<i className="inline-block h-3 w-[3px] rounded-sm bg-[#e0982e]" /> Rest <i className="inline-block h-3 w-[4px] rounded-sm bg-[#0e1220] ring-1 ring-white/60" /> Rest
</span> </span>
</div> </div>
</div> </div>
+10 -6
View File
@@ -10,15 +10,19 @@ export function riskLevel(score: number): RiskLevelKey {
return "low"; return "low";
} }
/** Zellen-Hintergrund der Heatmap (Mockup-Legende). */ /** Zellen-Hintergrund der Heatmap — kräftige Ampelfarben (auf Dunkel kontrastreich). */
export const RISK_CELL_COLORS: Record<RiskLevelKey, string> = { export const RISK_CELL_COLORS: Record<RiskLevelKey, string> = {
low: "#dff3e5", low: "#2ea86b",
medium: "#fdf0cf", medium: "#e3b427",
elevated: "#fbdcc0", elevated: "#e2802e",
high: "#f6c3c1", high: "#e0553f",
critical: "#ef9a98", critical: "#d63c5e",
}; };
/** Sättigungsstarke Farbskala grün→rot für den Risiko-Score-Balken. */
export const RISK_SCALE_GRADIENT =
"linear-gradient(90deg,#2ec76b 0%,#e3b427 32%,#e2802e 60%,#e0553f 82%,#d63c5e 100%)";
/** Pillen-Ton je Stufe — gemäß Heatmap-Skala: Grün → Gelb → Orange → Rot. */ /** Pillen-Ton je Stufe — gemäß Heatmap-Skala: Grün → Gelb → Orange → Rot. */
export const RISK_PILL_TONE: Record<RiskLevelKey, "ok" | "warn" | "orange" | "risk"> = { export const RISK_PILL_TONE: Record<RiskLevelKey, "ok" | "warn" | "orange" | "risk"> = {
low: "ok", low: "ok",