fix(onboarding,integrations,cycle): deep-link source chips + cycle settings wrench

- Onboarding 'more sources' chips anchor to their provider card
  (/settings/integrations#oura etc.); connection cards gain scroll anchors.
  Apple Health (no web card) stays on the page root.
- Cycle module gains a header settings wrench for parity with labs /
  medications / illness; the tab strip is now controlled so the wrench jumps
  to the settings tab and ?tab= deep-links keep working.
This commit is contained in:
Marc-André Bombeck committed 2026-07-08 23:59:10 +02:00
1 parent 188662311a
commit e5ca125dfb
3 files changed
+69 -18

No files matched your search

+37 -10
View File
@@ -1,9 +1,15 @@
"use client";
import { useMemo, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import dynamic from "next/dynamic";
import { useSearchParams } from "next/navigation";
import { Loader2, Plus, RefreshCw, Sparkles } from "lucide-react";
import {
Loader2,
Plus,
RefreshCw,
SlidersHorizontal,
Sparkles,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
@@ -100,6 +106,14 @@ export function CycleView() {
: "calendar";
}, [searchParams]);
// Controlled so the header "cycle settings" wrench (parity with the
// labs/medications/illness modules, which expose a customize glyph) can jump
// to the settings tab; a `?tab=` deep-link change still switches too.
const [tab, setTab] = useState<CycleTab>(initialTab);
useEffect(() => {
setTab(initialTab);
}, [initialTab]);
const today = useMemo(() => shiftToday(0), []);
const from = useMemo(() => shiftToday(-90), []);
const to = useMemo(() => shiftToday(180), []);
@@ -158,13 +172,26 @@ export function CycleView() {
title={<span data-tour-id="cycle-hero">{t("cycle.title")}</span>}
description={t("cycle.subtitle")}
actions={
<Button
onClick={() => openSheet(today)}
className="min-h-11 sm:min-h-9"
>
<Plus className="h-4 w-4" />
{t("cycle.logToday")}
</Button>
<>
<Button
variant="outline"
size="icon"
className="min-h-11 min-w-11 sm:min-h-9 sm:min-w-9"
aria-label={t("cycle.tabs.settings")}
title={t("cycle.tabs.settings")}
data-slot="cycle-settings-wrench"
onClick={() => setTab("settings")}
>
<SlidersHorizontal className="h-4 w-4" aria-hidden="true" />
</Button>
<Button
onClick={() => openSheet(today)}
className="min-h-11 sm:min-h-9"
>
<Plus className="h-4 w-4" />
{t("cycle.logToday")}
</Button>
</>
}
/>
@@ -266,7 +293,7 @@ export function CycleView() {
) : null}
</div>
<Tabs defaultValue={initialTab}>
<Tabs value={tab} onValueChange={(v) => setTab(v as CycleTab)}>
{/* v1.15.10 — the four German labels (Kalender/Prognosen/
Erkenntnisse/Einstellungen) overflowed the `flex-1` equal-width
cells at 375 px and forced a horizontal scroll. Below `sm` the