mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 05:12:14 +00:00
fix(ui): drop stale padding-era overrides on CardHeader and CardContent
The Card has been a gap-based flex column since v1.4.33 (gap-4 md:gap-6; CardHeader carries no bottom padding), but 29 CardHeader pb-0/1/2/2.5 and 8 CardContent pt-6 overrides from the padding-era shadcn card survived. Under the gap model they invert their intent: pb-* renders gap PLUS padding (looser, not tighter), pb-0 is a no-op, and pt-6 on a header-less CardContent stacks on the Card's own py-4/6 and makes the card top-heavy (40-48 px top vs 16-24 px bottom). Delete them all; a genuinely tighter header-to-body distance is expressed on the Card itself (className="gap-2"), the only knob that controls it. An ESLint guard for these slots is a follow-up.
This commit is contained in:
1 parent
e652ec146a
commit
21b65788ae
21 files changed
+36
-36
No files matched your search
@@ -211,7 +211,7 @@ export default function InsightsMedikamentePage() {
|
||||
: t("medications.categoryOther");
|
||||
return (
|
||||
<Card key={med.id} className="gap-2 py-4 md:gap-3 md:py-5">
|
||||
<CardHeader className="pb-0">
|
||||
<CardHeader>
|
||||
<TileHeader icon={Pill} title={med.name} />
|
||||
<div className="text-muted-foreground mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs">
|
||||
<span className="font-medium tabular-nums">{med.dose}</span>
|
||||
|
||||
@@ -996,7 +996,7 @@ export function MoodChart({
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
{/* v1.4.19 A2 — mobile-first header: stack title row above
|
||||
controls row on small viewports so the bucket / comparison
|
||||
chips never push the range tabs into a 2nd line. ≥sm goes
|
||||
|
||||
@@ -268,13 +268,13 @@ export function CustomMetricDetail({
|
||||
|
||||
{isLoading ? (
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<CardContent>
|
||||
<Skeleton className="h-60 w-full" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : entries.length === 0 ? (
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<CardContent>
|
||||
<EmptyState
|
||||
icon={<Gauge className="size-6" />}
|
||||
title={t("customMetrics.detail.emptyTitle")}
|
||||
@@ -296,7 +296,7 @@ export function CustomMetricDetail({
|
||||
icon={Gauge}
|
||||
/>
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<CardContent>
|
||||
<CustomMetricChart
|
||||
entries={entries}
|
||||
unit={metric?.unit ?? ""}
|
||||
|
||||
@@ -109,7 +109,7 @@ export function IllnessEpisodeDetail({ episodeId }: { episodeId: string }) {
|
||||
|
||||
{episode?.note ? (
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<CardContent>
|
||||
<p className="text-muted-foreground text-xs font-medium tracking-wide uppercase">
|
||||
{t("illness.detail.note")}
|
||||
</p>
|
||||
|
||||
@@ -132,7 +132,7 @@ function EpisodeCard({
|
||||
|
||||
return (
|
||||
<Card className="h-full gap-3 md:gap-3">
|
||||
<CardHeader className="pb-0">
|
||||
<CardHeader>
|
||||
<CardTitle className="min-w-0">
|
||||
<Link
|
||||
href={`/illness/${episode.id}`}
|
||||
|
||||
@@ -115,7 +115,7 @@ export function CorrelationCard({ result }: CorrelationCardProps) {
|
||||
TONE_BAR_CLASSNAME[result.kind],
|
||||
)}
|
||||
/>
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<div className="space-y-0.5">
|
||||
<CardTitle className="text-sm font-semibold">{title}</CardTitle>
|
||||
|
||||
@@ -50,7 +50,7 @@ export function GlucoseClinicalPanel() {
|
||||
if (query.isLoading) {
|
||||
return (
|
||||
<Card data-slot="glucose-clinical-panel-skeleton">
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
<Skeleton className="h-5 w-40" />
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
@@ -96,7 +96,7 @@ export function GlucoseClinicalPanel() {
|
||||
|
||||
return (
|
||||
<Card data-slot="glucose-clinical-panel" data-state="learning">
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2 text-base font-semibold">
|
||||
<Droplet className="h-4 w-4" aria-hidden="true" />
|
||||
{t("insights.bloodGlucose.clinical.learningTitle")}
|
||||
@@ -132,7 +132,7 @@ export function GlucoseClinicalPanel() {
|
||||
|
||||
return (
|
||||
<Card data-slot="glucose-clinical-panel" data-state="asserted">
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<CardTitle className="flex items-center gap-2 text-base font-semibold">
|
||||
<Droplet className="h-4 w-4" aria-hidden="true" />
|
||||
|
||||
@@ -109,7 +109,7 @@ export function InsightStatusCard({
|
||||
data-testid="insight-status-card-preparing"
|
||||
className="gap-1.5 py-4 md:py-5"
|
||||
>
|
||||
<CardHeader className="pb-1">
|
||||
<CardHeader>
|
||||
<TileHeader icon={nodeIcon(icon)} title={title} />
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2">
|
||||
@@ -146,7 +146,7 @@ export function InsightStatusCard({
|
||||
// baseline across every assessment-card state.
|
||||
className="gap-1.5 py-4 md:py-5"
|
||||
>
|
||||
<CardHeader className="pb-1">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Skeleton className="bg-muted h-5 w-5 rounded" />
|
||||
<Skeleton className="bg-muted h-4 w-32 rounded" />
|
||||
@@ -166,7 +166,7 @@ export function InsightStatusCard({
|
||||
if (!hasProvider) {
|
||||
return (
|
||||
<Card className="gap-1.5 py-4 opacity-80 md:py-5">
|
||||
<CardHeader className="pb-1">
|
||||
<CardHeader>
|
||||
<TileHeader icon={nodeIcon(icon)} title={title} />
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-1.5">
|
||||
@@ -188,7 +188,7 @@ export function InsightStatusCard({
|
||||
if (!text) {
|
||||
return (
|
||||
<Card className="gap-1.5 py-4 md:py-5">
|
||||
<CardHeader className="pb-1">
|
||||
<CardHeader>
|
||||
<TileHeader icon={nodeIcon(icon)} title={title} />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
@@ -231,7 +231,7 @@ export function InsightStatusCard({
|
||||
// sibling tiles. The loading skeleton keeps its own spacing.
|
||||
className="animate-insight-in gap-1.5 py-4 md:py-5"
|
||||
>
|
||||
<CardHeader className="pb-1">
|
||||
<CardHeader>
|
||||
{/* v1.11.5 — the top-right "cached" label was removed: it surfaced
|
||||
an implementation detail and devalued the assessment. The card
|
||||
still consumes the warm cache; it just no longer announces it.
|
||||
|
||||
@@ -312,7 +312,7 @@ function TargetReferencePanel({
|
||||
per-context label (Fasting / Postprandial / …) carries real,
|
||||
non-duplicative info, so it stays as a sub-caption under the
|
||||
header. */}
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
<TileHeader
|
||||
icon={Target}
|
||||
title={t("insights.target.heading")}
|
||||
|
||||
@@ -98,7 +98,7 @@ function MoodCorrelationCard({
|
||||
data-kind={kind}
|
||||
className={className}
|
||||
>
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<CardTitle className="text-sm font-semibold">
|
||||
{t(TITLE_KEY[kind])}
|
||||
|
||||
@@ -27,7 +27,7 @@ export function MoodInTargetTile({ pct }: { pct: number | null }) {
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
<TileHeader icon={Target} title={t("insights.mood.inTargetTitle")} />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
|
||||
@@ -167,7 +167,7 @@ function SectionCard({
|
||||
}) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
<TileHeader icon={icon} title={title} />
|
||||
</CardHeader>
|
||||
<CardContent>{children}</CardContent>
|
||||
@@ -289,7 +289,7 @@ export function MoodInsightsSections({
|
||||
// above its body instead of floating ~16-24 px above it.
|
||||
className="animate-insight-in gap-1.5 py-4 md:py-5"
|
||||
>
|
||||
<CardHeader className="pb-1">
|
||||
<CardHeader>
|
||||
<TileHeader
|
||||
icon={Sparkles}
|
||||
title={t("insights.mood.betterDays.title")}
|
||||
|
||||
@@ -44,7 +44,7 @@ export function MoodStabilityTile({
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
<TileHeader
|
||||
icon={Activity}
|
||||
title={t("insights.mood.stability.title")}
|
||||
|
||||
@@ -65,7 +65,7 @@ export function MoodWhatStandsOut({
|
||||
|
||||
return (
|
||||
<Card data-slot="mood-what-stands-out">
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
<TileHeader
|
||||
icon={TrendingUp}
|
||||
title={t("insights.mood.narrative.title")}
|
||||
|
||||
@@ -247,7 +247,7 @@ export function SleepHypnogram({ session }: SleepHypnogramProps) {
|
||||
// `gap-3` so the header sits closer to the timeline, reclaiming the empty
|
||||
// band the maintainer flagged. The chart keeps its 200 px footprint.
|
||||
<Card data-slot="sleep-hypnogram" className="gap-3 md:gap-3">
|
||||
<CardHeader className="pb-0">
|
||||
<CardHeader>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<CardTitle className="text-base font-semibold">
|
||||
{t("insights.sleep.hypnogram.title")}
|
||||
|
||||
@@ -209,7 +209,7 @@ export function SleepStageStackedBar({ breakdown }: SleepStageStackedBarProps) {
|
||||
|
||||
return (
|
||||
<Card data-slot="sleep-stage-stacked-bar">
|
||||
<CardHeader className="pb-2">
|
||||
<CardHeader>
|
||||
<div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<CardTitle className="text-base font-semibold">
|
||||
|
||||
@@ -34,7 +34,7 @@ export function AverageSleepCard({ average }: { average: AverageSleepDto }) {
|
||||
if (average.state === "partial") {
|
||||
return (
|
||||
<Card data-slot="average-sleep-card">
|
||||
<CardHeader className="pb-0">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<BedDouble className="text-info h-4 w-4" />
|
||||
<CardTitle className="text-base font-semibold">
|
||||
@@ -58,7 +58,7 @@ export function AverageSleepCard({ average }: { average: AverageSleepDto }) {
|
||||
|
||||
return (
|
||||
<Card data-slot="average-sleep-card">
|
||||
<CardHeader className="pb-0">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<BedDouble className="text-info h-4 w-4" />
|
||||
<CardTitle className="text-base font-semibold">
|
||||
|
||||
@@ -47,7 +47,7 @@ export function ChronotypeCard({ chronotype }: { chronotype: ChronotypeDto }) {
|
||||
const need = chronotype.freeNightsCounted + chronotype.freeNightsUntilReady;
|
||||
return (
|
||||
<Card data-slot="chronotype-card">
|
||||
<CardHeader className="pb-0">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Clock className="text-info h-4 w-4" />
|
||||
<CardTitle className="text-base font-semibold">
|
||||
@@ -73,7 +73,7 @@ export function ChronotypeCard({ chronotype }: { chronotype: ChronotypeDto }) {
|
||||
|
||||
return (
|
||||
<Card data-slot="chronotype-card">
|
||||
<CardHeader className="pb-0">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Clock className="text-info h-4 w-4" />
|
||||
<CardTitle className="text-base font-semibold">
|
||||
|
||||
@@ -32,7 +32,7 @@ export function SleepDebtCard({ debt }: { debt: SleepDebtDto }) {
|
||||
if (debt.state === "partial") {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="pb-0">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Moon className="text-info h-4 w-4" />
|
||||
<CardTitle className="text-base font-semibold">
|
||||
@@ -64,7 +64,7 @@ export function SleepDebtCard({ debt }: { debt: SleepDebtDto }) {
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="pb-0">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Moon className="text-info h-4 w-4" />
|
||||
<CardTitle className="text-base font-semibold">
|
||||
|
||||
@@ -353,13 +353,13 @@ export function LabBiomarkerDetail({ biomarkerId }: { biomarkerId: string }) {
|
||||
|
||||
{isLoading ? (
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<CardContent>
|
||||
<Skeleton className="h-60 w-full" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : readings.length === 0 ? (
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<CardContent>
|
||||
<EmptyState
|
||||
icon={<FlaskConical className="size-6" />}
|
||||
title={t("labs.detail.emptyTitle")}
|
||||
@@ -376,7 +376,7 @@ export function LabBiomarkerDetail({ biomarkerId }: { biomarkerId: string }) {
|
||||
// Qualitative marker — no numeric strip / chart. Show the latest
|
||||
// result text on its own simple line, no unit, no range badge.
|
||||
<Card>
|
||||
<CardContent className="space-y-1 pt-6">
|
||||
<CardContent className="space-y-1">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
{t("labs.detail.latestResult")}
|
||||
</p>
|
||||
@@ -394,7 +394,7 @@ export function LabBiomarkerDetail({ biomarkerId }: { biomarkerId: string }) {
|
||||
icon={FlaskConical}
|
||||
/>
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<CardContent>
|
||||
<LabBiomarkerChart
|
||||
readings={readings}
|
||||
unit={marker?.unit ?? latest?.unit ?? ""}
|
||||
|
||||
@@ -126,7 +126,7 @@ export function MedicationCardHeader({
|
||||
);
|
||||
|
||||
return (
|
||||
<CardHeader className="pb-2.5">
|
||||
<CardHeader>
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
{href ? (
|
||||
<Link
|
||||
|
||||
Reference in new issue
Block a user