mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 06:40:50 +00:00
The target reference card carried an inline "Adjust target range" link, which read as a control buried in a read surface. Lift the action to a gear button in the category-page header, to the left of the Coach launch icon, so the two sit as a consistent icon cluster beside the heading. A small page-scoped provider bridges the two: the reference card registers its editable target (one per page, except blood glucose which fans out to several contexts and registers each) and the header gear opens the per-metric editor sheet the provider owns. Single-target pages open that target directly; glucose opens the primary context, since target editing lives only on these pages — there is no separate targets management surface. The card itself is now a pure read surface. The gear carries the action's existing label as its accessible name, clears the 44 px touch-target floor on mobile, and exposes a stable `data-slot` for end-to-end coverage.
62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
"use client";
|
|
|
|
import { Settings2 } from "lucide-react";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import { cn } from "@/lib/utils";
|
|
import { useTranslations } from "@/lib/i18n/context";
|
|
import { useTargetAdjust } from "@/lib/insights/target-adjust-context";
|
|
|
|
/**
|
|
* Header gear that opens the per-metric target editor.
|
|
*
|
|
* The "Adjust target range" affordance used to sit inside the target
|
|
* reference card; it now lives in the Insights category-page header
|
|
* (`<SubPageShell>`), to the left of the Coach launch icon, so the card
|
|
* stays a read surface. The button is a thin wrapper around
|
|
* `useTargetAdjust()`:
|
|
*
|
|
* - renders nothing when no provider is mounted or no editable target
|
|
* has registered for the page (e.g. a metric without a numeric
|
|
* target band, where the card paints nothing), so the header never
|
|
* shows a dead control;
|
|
* - opens the primary registered target's `<TargetEditSheet>` on click.
|
|
*
|
|
* Sized to match `<CoachLaunchButton variant="icon">` so the gear + the
|
|
* Coach sparkle read as a consistent icon cluster top-right of the
|
|
* heading.
|
|
*/
|
|
export function TargetAdjustButton({ className }: { className?: string }) {
|
|
const { t } = useTranslations();
|
|
const adjust = useTargetAdjust();
|
|
|
|
// No provider, or no editable target registered for this page.
|
|
if (!adjust || !adjust.canAdjust) return null;
|
|
|
|
// Reuse the action's existing copy ("Adjust target range" /
|
|
// "Zielbereich anpassen") — the gear performs exactly what the old
|
|
// in-card link did, so the same string is the right accessible label.
|
|
const label = t("insights.subPage.target.adjustLink");
|
|
|
|
return (
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
size="icon"
|
|
data-slot="target-adjust-trigger"
|
|
aria-label={label}
|
|
title={label}
|
|
onClick={() => adjust.requestAdjust()}
|
|
className={cn(
|
|
// The `icon` size is 40 px; bump to the 44 px WCAG 2.5.5 floor on
|
|
// mobile and settle back to the 40 px that matches the sibling
|
|
// Coach icon from `sm` up, so the cluster reads as one on desktop.
|
|
"text-muted-foreground hover:text-foreground size-11 sm:size-10",
|
|
className,
|
|
)}
|
|
>
|
|
<Settings2 className="size-4" aria-hidden="true" />
|
|
</Button>
|
|
);
|
|
}
|