mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
fix(medications): keep the card a constant neutral surface, never tint by dose status
The v1.15.9 take-window highlight washed the whole medication card green (ring + tinted background) when a dose was in its on-time window. A card turning green reads as an imperative "take it now" and drowns the rest of the page once several doses fall due. Drop the surface tint entirely so the card stays a constant neutral surface; the take-now / overdue / very-overdue status remains, expressed only through the discreet top status line / pill (text + glyph), never as a background or border colour. Tests assert the neutral surface across every dose status plus the surviving status pill.
This commit is contained in:
1 parent
e523a3ae00
commit
6f5f035b78
2 files changed
+39
-24
No files matched your search
@@ -373,10 +373,11 @@ describe("streak-token parity — generic vs GLP-1 card", () => {
|
||||
});
|
||||
|
||||
/**
|
||||
* v1.15.9 — the ONE shared `<MedicationCardBody>` both cards render. These
|
||||
* tests pin the state-driven presentation (green take-window highlight,
|
||||
* overdue / heavily-overdue top line) and the structural identity that makes
|
||||
* the two variants impossible to diverge — they pass content into THIS body.
|
||||
* v1.15.18 — the ONE shared `<MedicationCardBody>` both cards render. These
|
||||
* tests pin that the card surface is a CONSTANT neutral surface — dose status
|
||||
* is never expressed as a background / border tint (Marc, recurring) — while
|
||||
* status is still surfaced via the discreet top line / pill, plus the
|
||||
* structural identity that makes the two variants impossible to diverge.
|
||||
*/
|
||||
describe("medication card body — shared shell + dose-state presentation", () => {
|
||||
function renderBody(doseStatus: DoseStatus, active = true) {
|
||||
@@ -406,17 +407,30 @@ describe("medication card body — shared shell + dose-state presentation", () =
|
||||
);
|
||||
}
|
||||
|
||||
it("highlights the card green when the dose is in its take-window", () => {
|
||||
it("never tints the card surface when the dose is in its take-window", () => {
|
||||
// Marc (recurring): the whole card washing green reads as "take it now"
|
||||
// and is a permanent removal. The take-window status survives ONLY as the
|
||||
// discreet "Take now" pill, never as a card background / ring tint.
|
||||
const html = renderBody("on_time_window");
|
||||
// Green ring + tinted background on the Card shell.
|
||||
expect(html).toContain("ring-success/40");
|
||||
expect(html).toContain("bg-success/5");
|
||||
expect(html).not.toContain("ring-success/40");
|
||||
expect(html).not.toContain("bg-success/5");
|
||||
// The discreet status pill still communicates the state.
|
||||
expect(html).toContain("Take now");
|
||||
});
|
||||
|
||||
it("stays calm (no green highlight) for upcoming / taken states", () => {
|
||||
for (const status of ["upcoming", "taken_on_time", "taken_late", "skipped"] as const) {
|
||||
it("never tints the card surface across any dose status", () => {
|
||||
for (const status of [
|
||||
"on_time_window",
|
||||
"upcoming",
|
||||
"taken_on_time",
|
||||
"taken_late",
|
||||
"skipped",
|
||||
"overdue",
|
||||
"missed",
|
||||
] as const) {
|
||||
const html = renderBody(status);
|
||||
expect(html).not.toContain("ring-success/40");
|
||||
expect(html).not.toContain("bg-success/5");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -433,9 +447,10 @@ describe("medication card body — shared shell + dose-state presentation", () =
|
||||
expect(html).toContain("text-destructive");
|
||||
});
|
||||
|
||||
it("never highlights green on an inactive medication", () => {
|
||||
it("keeps the inactive surface muted without any status tint", () => {
|
||||
const html = renderBody("on_time_window", false);
|
||||
expect(html).not.toContain("ring-success/40");
|
||||
expect(html).not.toContain("bg-success/5");
|
||||
expect(html).toContain("opacity-60");
|
||||
});
|
||||
|
||||
|
||||
@@ -35,11 +35,16 @@ import type { MedicationWindowStatus } from "@/lib/medications/window-status";
|
||||
* the single `mt-auto pt-0` action wrapper — there is no per-variant spacing
|
||||
* left to diverge.
|
||||
*
|
||||
* State-driven presentation (like the iOS app):
|
||||
* - `on_time_window` → the card highlights green (`ring` + tinted bg): the
|
||||
* actionable "take it now" state stands out at a glance.
|
||||
* State-driven presentation:
|
||||
* - The card surface itself is a CONSTANT neutral surface — dose status
|
||||
* never tints the card background or border. A whole card washing green
|
||||
* reads as "take it now everywhere" and drowns the page; status is shown
|
||||
* ONLY through the discreet top line / pill below.
|
||||
* - `on_time_window` → the discreet "Take now" pill (success-toned text +
|
||||
* glyph), no card wash.
|
||||
* - `overdue` → a calm top status line; `missed` (at / past the miss
|
||||
* cutoff) escalates to "Stark überfällig" in the destructive tone.
|
||||
* cutoff) escalates to "Stark überfällig" in the destructive tone — both
|
||||
* are a single text line with an icon, not a surface tint.
|
||||
* - `upcoming` / `taken_*` / `skipped` → no escalation; the card stays calm.
|
||||
*/
|
||||
export interface MedicationCardBodyProps {
|
||||
@@ -123,10 +128,6 @@ export function MedicationCardBody({
|
||||
}: MedicationCardBodyProps) {
|
||||
const { t } = useTranslations();
|
||||
|
||||
// Green take-window highlight — the actionable "take it now" state, mirrored
|
||||
// from the iOS card. Suppressed on an inactive med (it carries no actions).
|
||||
const inTakeWindow = active && doseStatus === "on_time_window";
|
||||
|
||||
// Overdue escalation line: a dose past its on-time window. `missed` (at /
|
||||
// past the clinical miss cutoff) reads "Stark überfällig"; the still-takeable
|
||||
// `overdue` tail reads the calmer "Überfällig". Both use the destructive
|
||||
@@ -140,11 +141,10 @@ export function MedicationCardBody({
|
||||
|
||||
return (
|
||||
<Card
|
||||
className={cn(
|
||||
"h-full",
|
||||
active ? "" : "opacity-60",
|
||||
inTakeWindow && "ring-success/40 bg-success/5 ring-1",
|
||||
)}
|
||||
// The card surface is a constant neutral surface — dose status is never
|
||||
// expressed as a background / border tint (Marc, recurring): only the
|
||||
// discreet status line / pill below communicates take-now / overdue.
|
||||
className={cn("h-full", active ? "" : "opacity-60")}
|
||||
>
|
||||
<MedicationCardHeader
|
||||
name={name}
|
||||
|
||||
Reference in new issue
Block a user