mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 21:32:18 +00:00
grid-rows-[auto_auto] was unconditional, so a header with a title and no CardDescription still reserved an empty second row track and drew the gap-2 for it — 32px instead of the intended 24px between heading and body on desktop. Make the second row conditional on a description being present, and widen CardAction to row-span-full so it still tracks the header's row count when an action lands in a description-less card. Also correct two assessment cards that had drifted onto gap-1.5 instead of the sanctioned gap-2 compact tier.
109 lines
2.7 KiB
TypeScript
109 lines
2.7 KiB
TypeScript
import * as React from "react";
|
|
|
|
import { cn } from "@/lib/utils";
|
|
|
|
/**
|
|
* v1.4.33 IW9 — Card padding normalised on `p-4 md:p-6`.
|
|
*
|
|
* Pre-v1.4.33 the shadcn defaults shipped `py-6` + `px-6` (uniform
|
|
* 24 px on every breakpoint) while the dashboard tile-strip + chart
|
|
* cards used `p-4 md:p-6` (16 px mobile, 24 px md+). Side-by-side on
|
|
* `/insights` the correlation cards + daily-briefing read as "denser"
|
|
* than the chart cards next to them; the visual reads as two card
|
|
* languages on the same page. Matching the dashboard token here gives
|
|
* the whole app a single card-padding contract.
|
|
*
|
|
* Refs `.planning/round-v1433-audit-polish.md` §4.1 + Win 4.
|
|
*/
|
|
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card"
|
|
className={cn(
|
|
"bg-card text-card-foreground flex flex-col gap-4 rounded-xl border py-4 shadow-sm md:gap-6 md:py-6",
|
|
className,
|
|
)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-header"
|
|
className={cn(
|
|
"@container/card-header grid auto-rows-min items-start gap-2 px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] md:px-6 [.border-b]:pb-4 md:[.border-b]:pb-6",
|
|
className,
|
|
)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-title"
|
|
className={cn("leading-none font-semibold", className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-description"
|
|
className={cn("text-muted-foreground text-sm", className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-action"
|
|
className={cn(
|
|
"col-start-2 row-span-full row-start-1 self-start justify-self-end",
|
|
className,
|
|
)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-content"
|
|
className={cn("px-4 md:px-6", className)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="card-footer"
|
|
className={cn(
|
|
"flex items-center px-4 md:px-6 [.border-t]:pt-4 md:[.border-t]:pt-6",
|
|
className,
|
|
)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export {
|
|
Card,
|
|
CardHeader,
|
|
CardFooter,
|
|
CardTitle,
|
|
CardAction,
|
|
CardDescription,
|
|
CardContent,
|
|
};
|