mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 06:06:10 +00:00
fix(insights): move coach-ask to the header and de-emphasise the assessment border
The Coach launch sat at the foot of every category page; move it into the
sub-page header as an icon-only button at heading height, top-right, so
"ask the coach" reads as a header action and the page no longer ends on a
stray button. The shared shell mounts it (gated on the Coach flag plus the
per-user opt-out), so every category page picks it up and the foot
instance is dropped. Also drop the purple left accent on the assessment
("Einschätzung") card — the coloured rule made it read as restless against
the calmer surrounding cards.
This commit is contained in:
1 parent
4935a9b000
commit
6e61713fc6
12 files changed
+68
-53
No files matched your search
@@ -33,12 +33,24 @@ export interface CoachLaunchButtonProps {
|
||||
prefill?: string;
|
||||
/** Optional className passthrough for inline overrides. */
|
||||
className?: string;
|
||||
/**
|
||||
* v1.8.6 — render the launch as an icon-only affordance instead of the
|
||||
* labelled pill. The sub-page shell mounts this variant at heading
|
||||
* height in the page header so "Coach fragen" sits top-right, aligned
|
||||
* with the title, rather than at the foot of the page. The accessible
|
||||
* label still resolves the shared CTA copy via `aria-label`. The icon
|
||||
* variant stays visible across breakpoints — it is the header's own
|
||||
* Coach entry, not the `lg+`-only inline pill the old foot placement
|
||||
* used (the mobile FAB covers `<lg` for that legacy surface).
|
||||
*/
|
||||
variant?: "inline" | "icon";
|
||||
}
|
||||
|
||||
export function CoachLaunchButton({
|
||||
label,
|
||||
prefill,
|
||||
className,
|
||||
variant = "inline",
|
||||
}: CoachLaunchButtonProps) {
|
||||
const { t } = useTranslations();
|
||||
const launch = useCoachLaunch();
|
||||
@@ -59,6 +71,26 @@ export function CoachLaunchButton({
|
||||
|
||||
const accessibleLabel = label ?? t("insights.heroActionAskCoach");
|
||||
|
||||
if (variant === "icon") {
|
||||
// v1.8.6 — heading-height icon button mounted by the sub-page shell.
|
||||
// Icon-only so it reads as a compact action beside the title; the
|
||||
// CTA copy moves to `aria-label` + a native tooltip.
|
||||
return (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
data-slot="coach-launch-icon"
|
||||
aria-label={accessibleLabel}
|
||||
title={accessibleLabel}
|
||||
onClick={() => launch.askCoach(prefill ?? null)}
|
||||
className={cn("text-muted-foreground hover:text-foreground", className)}
|
||||
>
|
||||
<Sparkles className="size-4" aria-hidden="true" />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
// Inline header-style action on `lg+`. Hidden below `lg` because the
|
||||
// layout-level FAB (`<LayoutCoachFab>`) covers that breakpoint —
|
||||
// mounting both at the same time would put two affordances in front
|
||||
|
||||
@@ -10,7 +10,6 @@ import { useTranslations } from "@/lib/i18n/context";
|
||||
import type { InsightMetric } from "@/lib/insights/metric-availability";
|
||||
import type { ChartOverlayKey } from "@/lib/dashboard-layout";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { CoachLaunchButton } from "@/components/insights/coach-launch-button";
|
||||
import { HealthChartDynamic } from "@/components/charts/health-chart-dynamic";
|
||||
import { MetricEmptyState } from "@/components/insights/metric-empty-state";
|
||||
import { MetricStatStrip } from "@/components/insights/metric-stat-strip";
|
||||
@@ -33,8 +32,9 @@ import { SubPageShell } from "@/components/insights/sub-page-shell";
|
||||
* pass `null` to render an onboarding hint without a dead link.
|
||||
* 3. `<HealthChartDynamic>` mounted on the canonical
|
||||
* `ChartOverlayKey` so the chart-cog popover persists per metric.
|
||||
* 4. `<CoachLaunchButton>` at the foot — feature-flag gating runs
|
||||
* inside the button so this scaffold stays agnostic.
|
||||
* 4. A header-height Coach launch icon (`coachLaunch` on the shell) —
|
||||
* feature-flag gating runs inside the button so this scaffold stays
|
||||
* agnostic.
|
||||
*
|
||||
* Adding a new metric is a four-line page module that hands the right
|
||||
* Zod / MeasurementType + ChartOverlayKey + i18n-key prefix to this
|
||||
@@ -181,6 +181,7 @@ export function HealthKitMetricPage({
|
||||
timeZone={user?.timezone ?? undefined}
|
||||
/>
|
||||
}
|
||||
coachLaunch
|
||||
showAllValuesType={measurementType}
|
||||
>
|
||||
<HealthChartDynamic
|
||||
@@ -198,7 +199,6 @@ export function HealthKitMetricPage({
|
||||
{targetSummarySlug ? (
|
||||
<MetricTargetSummary slug={targetSummarySlug} />
|
||||
) : null}
|
||||
<CoachLaunchButton />
|
||||
</SubPageShell>
|
||||
);
|
||||
}
|
||||
@@ -163,7 +163,12 @@ export function InsightStatusCard({
|
||||
// shell padding to `py-4 md:py-5` so the assessment block reads tight
|
||||
// in the denser sub-page rhythm. The same override lands on every
|
||||
// status variant below so the gap is consistent across states.
|
||||
className="animate-insight-in border-l-dracula-purple gap-2 border-l-2 py-4 md:gap-3 md:py-5"
|
||||
//
|
||||
// v1.8.6 — drop the purple left accent (`border-l-dracula-purple
|
||||
// border-l-2`). The coloured rule made the assessment card read as
|
||||
// restless against the calmer surrounding cards; the plain card
|
||||
// border carries enough separation on its own.
|
||||
className="animate-insight-in gap-2 py-4 md:gap-3 md:py-5"
|
||||
>
|
||||
<CardHeader className="pb-2">
|
||||
<div className="flex items-center justify-between">
|
||||
|
||||
Reference in new issue
Block a user