Frontend redesign chunk 2: primitives and marks
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.
This commit is contained in:
@@ -5,16 +5,25 @@
|
||||
* 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: "bg-gray-800/40 text-gray-600",
|
||||
minor: "bg-gray-800 text-gray-400",
|
||||
moderate: "bg-orange-950 text-orange-400",
|
||||
major: "bg-red-950 text-red-400",
|
||||
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 {
|
||||
@@ -26,11 +35,8 @@ 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 (
|
||||
<span className={`text-xs font-mono px-2 py-0.5 rounded-full ${SEVERITY_COLORS[severity]}`}>
|
||||
{SEVERITY_LABEL[severity]}
|
||||
</span>
|
||||
);
|
||||
return <SeverityMark severity={severity} showLabel />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user