Rewrite components/ui/* (Button, Card, Badge, PageHeader, EmptyState, Skeleton) against the chunk-1 tokens instead of hardcoded gray-9xx classes, and drop the remaining font-mono from label/heading text. Add the three colour-blindness-validated encoding components from UI_REDESIGN.md §2.3: - components/marks/SeverityMark.tsx — glyph (filled triangle / outline triangle / outline circle) + optional spine + optional label, from the four-level severity ladder. Colour is never the only channel. - components/marks/TypeGlyph.tsx — five stroked SVG glyphs (fire, police, ems, collision, other) in currentColor. Incident type is now shape, not hue, since five hues can't clear an all-pairs CVD gate. - components/marks/NodeMark.tsx — diamond at four weights (filled+ring / filled / hollow / hollow-dashed). Green is gone from node state entirely. lib/severity.tsx now renders through SeverityMark; SEVERITY_COLORS reads the validated sev-moderate/sev-major tokens with routine/minor neutral. IncidentBadges.tsx's TypeBadge is reimplemented on TypeGlyph instead of a coloured pill. Per UI_REDESIGN.md chunk 2.
43 lines
2.0 KiB
TypeScript
43 lines
2.0 KiB
TypeScript
/**
|
|
* Shared severity ladder for calls and incidents: routine < minor < moderate < major.
|
|
* Every call/incident gets one of these four. `"unknown"` (and any other
|
|
* unrecognized value) is a legacy value still present on historical docs —
|
|
* treat it as "no severity", not as a fifth level.
|
|
*/
|
|
import type { ReactElement } from "react";
|
|
import { SeverityMark } from "@/components/marks/SeverityMark";
|
|
|
|
export type Severity = "routine" | "minor" | "moderate" | "major";
|
|
|
|
export const SEVERITY_ORDER: Record<Severity, number> = { routine: 0, minor: 1, moderate: 2, major: 3 };
|
|
export const SEVERITY_LABEL: Record<Severity, string> = { routine: "Routine", minor: "Minor", moderate: "Moderate", major: "Major" };
|
|
|
|
/**
|
|
* Validated against the dataviz all-pairs colour-blindness checker (see
|
|
* UI_REDESIGN.md §2.3). Severity is the ONLY hue channel in the whole app —
|
|
* moderate/major carry colour, routine/minor are neutral ink with no hue.
|
|
* Colour is never the sole channel: SeverityMark also carries glyph shape
|
|
* and spine thickness so the ladder survives grayscale.
|
|
*/
|
|
export const SEVERITY_COLORS: Record<Severity, string> = {
|
|
routine: "var(--ink-muted)",
|
|
minor: "var(--ink-2)",
|
|
moderate: "var(--sev-moderate)",
|
|
major: "var(--sev-major)",
|
|
};
|
|
|
|
export function isKnownSeverity(s: string | null | undefined): s is Severity {
|
|
return s === "routine" || s === "minor" || s === "moderate" || s === "major";
|
|
}
|
|
|
|
/** Legacy/unset severities rank below `routine` so a recency-sorted list never confuses them with a real (low) severity. */
|
|
export function severityRank(s: string | null | undefined): number {
|
|
return isKnownSeverity(s) ? SEVERITY_ORDER[s] : -1;
|
|
}
|
|
|
|
/** Renders the full severity mark (glyph + word chip). Use `<SeverityMark>` directly for more control (spine, size, label-off). */
|
|
export function severityBadge(severity: string | null | undefined): ReactElement | null {
|
|
if (!isKnownSeverity(severity)) return null;
|
|
return <SeverityMark severity={severity} showLabel />;
|
|
}
|