diff --git a/CHANGELOG.md b/CHANGELOG.md index f8de28c26..b81eb79a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [1.9.3] — 2026-06-02 — Medication card layout polish + +### Fixed + +- **The medication cards look right again.** A recent alignment change pushed each card's action buttons to the very bottom of the cell, which left an empty gap between a shorter card's content and its buttons when it sat next to a taller card in the grid. The buttons now sit directly under the card's content again; the cards still share a height and the dose rows still line up, without the gap. + ## [1.9.2] — 2026-06-02 — Document the medication compliance endpoint ### Changed diff --git a/docs/api/openapi.yaml b/docs/api/openapi.yaml index ffda5e6e9..4aac88a9c 100644 --- a/docs/api/openapi.yaml +++ b/docs/api/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: title: HealthLog API - version: 1.9.2 + version: 1.9.3 description: >- Self-hosted personal-health-tracking PWA — public API surface for the iOS native client and external ingest. diff --git a/e2e/medications-wizard-helpers.ts b/e2e/medications-wizard-helpers.ts index eba4a9f2a..2b99cb842 100644 --- a/e2e/medications-wizard-helpers.ts +++ b/e2e/medications-wizard-helpers.ts @@ -251,10 +251,20 @@ export async function expectMedicationOnList( page: Page, { name, withNextDueChip }: { name: string; withNextDueChip: boolean }, ): Promise { + // Pin the clock to a fixed afternoon before rendering the list. The + // recurring stub schedules an 08:00–09:00 window; the card derives its + // header from the real clock, so when CI happens to run inside that + // window the card shows the "take now" (in_window) pill and the + // "Nächste Einnahme:" next-due line is correctly suppressed — making the + // chip assertion below depend on the wall-clock. A fixed afternoon puts + // the morning window in the past so the next-due line always renders. + await page.clock.setFixedTime(new Date("2026-06-04T13:00:00Z")); await page.goto("/medications", { waitUntil: "domcontentloaded" }); const main = page.locator("main"); await expect(main.getByText(name).first()).toBeVisible({ timeout: 10_000 }); if (withNextDueChip) { - await expect(main.getByText(/Nächste Einnahme:/i).first()).toBeVisible(); + await expect(main.getByText(/Nächste Einnahme:/i).first()).toBeVisible({ + timeout: 10_000, + }); } } diff --git a/package.json b/package.json index 6bf1c3470..6feb7fcb2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "healthlog", - "version": "1.9.2", + "version": "1.9.3", "description": "Self-hosted personal-health-tracking PWA with Withings integration, AI insights, and doctor-report PDF export.", "license": "AGPL-3.0-only", "homepage": "https://healthlog.dev", diff --git a/src/components/medications/glp1-medication-card.tsx b/src/components/medications/glp1-medication-card.tsx index deb0c3d6d..876e5fe03 100644 --- a/src/components/medications/glp1-medication-card.tsx +++ b/src/components/medications/glp1-medication-card.tsx @@ -406,7 +406,7 @@ export function Glp1MedicationCard({ linkLabel={t("medications.openDetailPage")} /> - + {/* Take-now / overdue / very-overdue pill, shared with the generic medication card. The GLP-1 card historically omitted this row, which made Mounjaro feel different from @@ -423,13 +423,8 @@ export function Glp1MedicationCard({ {/* Injection state — last + next. The reserved min-height keeps a card whose last-injection line is absent the same vertical footprint as one that renders both lines, matching the generic - medication card's reserved last/next slot. This — together with - `h-full` + `mt-auto` — equalises the card height and pins a - shared bottom action baseline across the grid row. Note it does - NOT align the compliance bars row-for-row with a generic - sibling: the GLP-1-only rotation-hint block below pushes the - bars down by its own height, so only the header, the reserved - slot, and the pinned action row share a Y. */} + medication card's reserved last/next slot, so the dose rows line + up across the grid. */}
{medication.lastTakenAt && (

@@ -503,17 +498,15 @@ export function Glp1MedicationCard({ {/* Primary actions row — shared with the generic medication card. The GLP-1-specific side-effect quick-log lives in the header-actions overflow (kebab), not this row, so Mounjaro - and Ramipril share the canonical two-button primary row. - Pinned to the bottom with `mt-auto` so the action baseline is - shared across every card in the grid row, identical to the - generic medication card. */} + and Ramipril share the canonical two-button primary row. The + row sits directly after the content (the card still fills the + grid cell via h-full, but the actions are not pushed to the + bottom — that left a void between the content and the buttons). */} {medication.active && ( -

- -
+ )} diff --git a/src/components/medications/medication-card.tsx b/src/components/medications/medication-card.tsx index 26a2c9a11..407cb6442 100644 --- a/src/components/medications/medication-card.tsx +++ b/src/components/medications/medication-card.tsx @@ -311,7 +311,7 @@ export function MedicationCard({ linkLabel={t("medications.openDetailPage")} /> - + {/* Status, last & next intake info */} {currentWindowStatus.status && ( {nextSchedule && currentWindowStatus.status !== "in_window" && @@ -409,17 +408,15 @@ export function MedicationCard({ /> )} - {/* Quick actions — primary buttons of the medication card. - Pinned to the bottom with `mt-auto` so the action baseline is - shared across every card in the grid row regardless of how many - optional rows above it rendered. */} + {/* Quick actions — primary buttons of the medication card. They sit + directly after the content (the card still fills the grid cell via + h-full, but the actions are not pushed to the bottom — that left a + void between the content and the buttons on shorter cards). */} {medication.active && ( -
- -
+ )}