style(ui): pull off-scale spacing and micro-labels onto the scale

Sweep the spacing rests that sat off the 1/1.5/2/3/4/6/8/10 scale: the
health-score panels and their skeleton, the recommendation ask-Coach
gutter, the onboarding tour footer, the vaccination row, the danger-zone
alert margins, the recovery-codes action wrapper, and the chart-tooltip
tile. Move the last hand-written micro-sizes (coach counters, the
personal-record badge, the score-ring label, the dose-history and
cycle-calendar headers, the mood tag chips) onto the text-2xs token, and
give the documents upload buttons the mobile tap floor their peers set.
This commit is contained in:
Marc-André Bombeck committed 2026-08-09 11:27:05 +02:00
1 parent b6332a96d9
commit 7f6eae8425
15 files changed
+29 -23

No files matched your search

+1 -1
View File
@@ -282,7 +282,7 @@ function CoachConversationsBody() {
aria-hidden="true"
/>
{(c.attachments?.length ?? 0) > 1 ? (
<span className="text-[10px] font-semibold tabular-nums">
<span className="text-2xs font-semibold tabular-nums">
{c.attachments?.length}
</span>
) : null}
+1 -1
View File
@@ -73,7 +73,7 @@ export function RichChartTooltip({
return (
<div
data-slot="rich-chart-tooltip"
className="bg-card border-border min-w-[140px] rounded-xl border p-2.5 text-xs shadow-lg"
className="bg-card border-border min-w-[140px] rounded-xl border p-3 text-xs shadow-lg"
style={{
// The card itself is layered above the chart's own SVG; without
// an explicit background the gradient bleeds through the
+1 -1
View File
@@ -177,7 +177,7 @@ export function CycleCalendar({
<div
key={i}
role="columnheader"
className="text-muted-foreground pb-1 text-center text-[11px] font-medium uppercase"
className="text-muted-foreground text-2xs pb-1 text-center font-medium uppercase"
>
{wk}
</div>
+8 -2
View File
@@ -883,7 +883,10 @@ export function DocumentsView() {
description={t("documents.subtitle")}
actions={
canManage ? (
<Button onClick={() => uploadInputRef.current?.click()}>
<Button
className="min-h-11 sm:min-h-9"
onClick={() => uploadInputRef.current?.click()}
>
<Upload className="size-4" aria-hidden />
{t("documents.pageUpload")}
</Button>
@@ -940,7 +943,10 @@ export function DocumentsView() {
ctaSize="lg"
action={
canManage ? (
<Button onClick={() => uploadInputRef.current?.click()}>
<Button
className="min-h-11 sm:min-h-9"
onClick={() => uploadInputRef.current?.click()}
>
<Upload className="size-4" aria-hidden />
{t("documents.empty.action")}
</Button>
@@ -234,7 +234,7 @@ export function HistoryRail({
>
<Paperclip className="size-3.5" aria-hidden="true" />
{(c.attachments?.length ?? 0) > 1 ? (
<span className="text-[10px] font-semibold tabular-nums">
<span className="text-2xs font-semibold tabular-nums">
{c.attachments?.length}
</span>
) : null}
@@ -56,7 +56,7 @@ const SIZE: Record<
NonNullable<ScoreRingProps["size"]>,
{ px: number; numberClass: string; labelClass: string }
> = {
sm: { px: 120, numberClass: "text-3xl", labelClass: "text-[11px]" },
sm: { px: 120, numberClass: "text-3xl", labelClass: "text-2xs" },
md: { px: 168, numberClass: "text-5xl", labelClass: "text-xs" },
lg: { px: 232, numberClass: "text-7xl", labelClass: "text-sm" },
};
@@ -284,7 +284,7 @@ export function ScoreRing({
{!hasScore && (
<span
data-slot="score-ring-provisional"
className="text-muted-foreground absolute inset-x-0 bottom-0 line-clamp-1 px-1 text-center text-[10px] leading-tight"
className="text-muted-foreground text-2xs absolute inset-x-0 bottom-0 line-clamp-1 px-1 text-center leading-tight"
>
{t("insights.derived.scoreRing.provisionalCaption")}
</span>
@@ -310,7 +310,7 @@ export function HealthScoreCard({
PANEL_COLUMN_CLASS,
// `h-full` lets the hero band's `items-stretch` equalise the column
// against the greeting; `mt-auto` on the foot collects the slack.
"flex h-full flex-col gap-3.5",
"flex h-full flex-col gap-3",
className,
)}
>
@@ -827,7 +827,7 @@ export function HealthScoreCardSkeleton({ className }: { className?: string }) {
PANEL_CHROME_CLASS,
"border-border/60",
PANEL_COLUMN_CLASS,
"flex h-full flex-col gap-3.5",
"flex h-full flex-col gap-3",
PANEL_RESERVE_CLASS,
className,
)}
@@ -838,7 +838,7 @@ export function HealthScoreCardSkeleton({ className }: { className?: string }) {
keeps these blocks under the minimum above, so the minimum is the
thing that decides the height. */}
<Skeleton className="h-4 w-24" />
<Skeleton className="h-15 w-28" />
<Skeleton className="h-14 w-28" />
<Skeleton className="h-2 w-full rounded-full" />
<div className="space-y-1">
<Skeleton className="h-4 w-40" />
@@ -120,7 +120,7 @@ export function PersonalRecordBadge({
// green on the dark card (#50fa7b). Both clear 4.5:1 against
// their card background — the previous `text-success` on
// `bg-success/10` measured ~2.6:1 in dark mode.
"border-success/40 bg-success/15 text-success inline-flex shrink-0 items-center rounded-full border px-1.5 py-0.5 text-[10px] leading-none font-semibold tracking-wide uppercase tabular-nums",
"border-success/40 bg-success/15 text-success text-2xs inline-flex shrink-0 items-center rounded-full border px-1.5 py-0.5 leading-none font-semibold tracking-wide uppercase tabular-nums",
className,
)}
aria-label={t("insights.personalRecord.badge")}
@@ -443,7 +443,7 @@ export function RecommendationCard({
{/* v1.21.0 (C4 H2) — discreet "ask the Coach about this rec" link,
aligned under the rec text (the number gutter is `ml-6`). */}
<div className="mt-1 ml-5">
<div className="mt-1 ml-6">
<AskCoachAction
question={coachQuestion}
scope={coachScopeSource ? { metric: coachScopeSource } : undefined}
+2 -2
View File
@@ -184,7 +184,7 @@ export function MoodTagPicker({
}`}
>
<TagIcon className="h-5 w-5" aria-hidden="true" />
<span className="text-[11px] leading-tight">{label}</span>
<span className="text-2xs leading-tight">{label}</span>
</button>
);
})}
@@ -337,7 +337,7 @@ function AddTagTile({
className="border-border/70 text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-ring focus-visible:ring-offset-background flex min-h-16 w-[4.5rem] flex-col items-center justify-center gap-1 rounded-xl border border-dashed p-2 text-center transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
>
<Plus className="h-5 w-5" aria-hidden="true" />
<span className="text-[11px] leading-tight">{label}</span>
<span className="text-2xs leading-tight">{label}</span>
</button>
);
}
+1 -1
View File
@@ -695,7 +695,7 @@ export function OnboardingTour({
{/* `flex-wrap` keeps long localised labels (Skip / Back / Next) from
forcing a horizontal scrollbar inside the card — the row wraps
instead, so the primary action is always reachable. */}
<footer className="mt-5 flex flex-wrap items-center justify-between gap-2">
<footer className="mt-4 flex flex-wrap items-center justify-between gap-2">
<Button
type="button"
variant="ghost"
+2 -2
View File
@@ -108,7 +108,7 @@ function DataResetCard() {
{msg && (
<p
role="alert"
className={`mt-3 text-sm ${msgType === "success" ? "text-success" : "text-destructive"}`}
className={`text-sm ${msgType === "success" ? "text-success" : "text-destructive"}`}
>
{msg}
</p>
@@ -246,7 +246,7 @@ function AccountDeleteCard() {
{msg && (
<p
role="alert"
className={`mt-3 text-sm ${msgType === "success" ? "text-success" : "text-destructive"}`}
className={`text-sm ${msgType === "success" ? "text-success" : "text-destructive"}`}
>
{msg}
</p>
@@ -72,13 +72,13 @@ export function DoseHistoryColumnRulings() {
<dt className="text-foreground flex flex-wrap items-baseline gap-x-2 text-xs">
<code className="font-mono">{ruling.column}</code>
<span
className="text-muted-foreground text-[0.6875rem] uppercase"
className="text-muted-foreground text-2xs uppercase"
data-verdict={ruling.verdict}
>
{verdictFor(ruling.verdict)}
</span>
{ruling.jsonOnly && (
<span className="text-muted-foreground text-[0.6875rem]">
<span className="text-muted-foreground text-2xs">
{t("settings.sections.export.import.doseHistory.jsonOnly")}
</span>
)}
@@ -325,9 +325,9 @@ export function TotpCard({
{/* ── Fresh recovery codes (post-confirm or post-regen) ── */}
{freshCodes && (
<div>
<div className="space-y-3">
<RecoveryCodesPanel codes={freshCodes} />
<SettingsCardActions className="mt-3">
<SettingsCardActions>
<Button
type="button"
variant="outline"
@@ -172,7 +172,7 @@ function DoseRow({
: undefined
}
>
<CardContent className="flex items-center justify-between gap-3 px-4 py-2.5">
<CardContent className="flex items-center justify-between gap-3 px-4 py-3">
<div className="min-w-0 space-y-0.5">
<div className="flex flex-wrap items-center gap-x-2 text-sm">
{series ? (