chore(release): v1.28.43 — visual consistency polish

Verified UI-consistency findings from the campaign's design audit, each
pixel-faithful except the intended correction:

- insights hero band: off-scale py-5/gap-5 → the standard scale; H1
  font-semibold → font-bold; sm:text-[28px] → sm:text-3xl.
- medication-compliance-chart + recent-achievements-card: hand-rolled
  muted h-4 icon + text-sm headers → the standard TileHeader primitive so
  they match sibling tiles.
- achievements stat tiles + clinician-view shells: p-5 → p-4 md:p-6.
- two text-primary header glyphs (research-mode dialog, enroll-mfa) →
  text-foreground (never accent on a header glyph); the deliberate
  badge-boxed icons left untouched.
- SheetHeader now reserves the trailing close-X gutter like DialogHeader,
  closing the latent overlap class for future raw-Sheet consumers.
- five raw Dialogs on phone-reachable surfaces → ResponsiveSheet.
- new bg-card-scoped healthlog/spacing-scale lint (flags p-5/gap-5 etc.
  only on card shells; list-marker insets + half-steps excluded) at error,
  with the five offenders it flagged swept.
- dropped the stale CLAUDE.md '18 PascalCase outliers' line (0 remain).

Every data-slot preserved. No migration.
This commit is contained in:
Marc-André Bombeck committed 2026-07-16 03:44:00 +02:00
1 parent 3a9ed8dd0e
commit 6d83115d16
25 files changed
+717 -544

No files matched your search

@@ -202,6 +202,18 @@ describe("<RecentAchievementsCard>", () => {
expect(html).toContain("View all");
});
it("routes the header through the canonical TileHeader (foreground icon, h2)", () => {
mockData = { summary: {}, achievements: [], metrics: {} };
const html = render();
// Adopts the shared tile-header primitive so it matches sibling tiles…
expect(html).toContain('data-slot="tile-header"');
// …with the foreground (never muted) glyph and the h2 heading, not the
// old muted h-4 / text-sm row.
expect(html).toContain("Recent unlocks");
expect(html).not.toMatch(/<h2[^>]*text-sm font-semibold/);
expect(html).not.toContain("text-muted-foreground h-4 w-4");
});
it("renders up to three most-recent unlocks with title + date", () => {
mockData = {
summary: {},
@@ -25,6 +25,7 @@ import { formatDate } from "@/lib/format";
import { useAchievementsQuery } from "@/lib/queries/use-achievements-query";
import type { AchievementProgress } from "@/lib/gamification/achievements";
import { Skeleton } from "@/components/ui/skeleton";
import { TileHeader } from "@/components/insights/tile-header";
const iconMap: Record<string, LucideIcon> = {
Activity,
@@ -113,23 +114,23 @@ export function RecentAchievementsCard() {
data-slot="recent-achievements-card"
className="bg-card border-border space-y-3 rounded-xl border p-4 md:p-6"
>
<div className="flex items-center justify-between gap-3">
<div className="flex items-center gap-2">
<Trophy
className="text-muted-foreground h-4 w-4"
aria-hidden="true"
/>
<h2 className="text-sm font-semibold">
{t("achievements.dashboardCard.title")}
</h2>
</div>
<Link
href="/achievements"
className="text-muted-foreground hover:text-foreground inline-flex min-h-11 items-center text-xs"
>
{t("achievements.dashboardCard.viewAll")}
</Link>
</div>
{/* Canonical tile header (foreground h-5 icon, text-base h2) so the
dashboard card matches its sibling tiles instead of the old muted
h-4 / text-sm row. The "view all" link rides the header's right slot
(§11 inline-action-row). */}
<TileHeader
icon={Trophy}
titleAs="h2"
title={t("achievements.dashboardCard.title")}
right={
<Link
href="/achievements"
className="text-muted-foreground hover:text-foreground inline-flex min-h-11 items-center text-xs"
>
{t("achievements.dashboardCard.viewAll")}
</Link>
}
/>
{isPending ? (
<ul