diff --git a/src/app/settings/[section]/page.tsx b/src/app/settings/[section]/page.tsx index 87b97f90f..ceee2abed 100644 --- a/src/app/settings/[section]/page.tsx +++ b/src/app/settings/[section]/page.tsx @@ -30,8 +30,10 @@ import { import { SettingsShell } from "@/components/settings/settings-shell"; /** - * Dynamic settings section route. Each of the eight `SETTINGS_SECTION_SLUGS` - * is pre-rendered at build via `generateStaticParams()` so the URLs are + * Dynamic settings section route. Each of the `SETTINGS_SECTION_SLUGS` + * (16 today — 12 nav-visible sections plus the four routable-but-hidden + * Layout child editors) is pre-rendered at build via + * `generateStaticParams()` so the URLs are * statically known to Next.js, while the `dynamicParams = false` flag below * tells the router to 404 (instead of attempting on-demand rendering) for any * slug not in the list — which is exactly what `notFound()` would do at diff --git a/src/components/settings/dashboard-section.tsx b/src/components/settings/dashboard-section.tsx index 59f4e4dc1..346493ba2 100644 --- a/src/components/settings/dashboard-section.tsx +++ b/src/components/settings/dashboard-section.tsx @@ -1,6 +1,7 @@ "use client"; import { DashboardLayoutSection } from "@/components/settings/dashboard-layout-section"; +import { SettingsHubBackLink } from "@/components/settings/settings-hub-back-link"; import { useTranslations } from "@/lib/i18n/context"; export function DashboardSection() { @@ -11,7 +12,11 @@ export function DashboardSection() { aria-labelledby="settings-section-dashboard-title" className="space-y-6" > -
+
+

{t("settings.sections.dashboard.title")}

diff --git a/src/components/settings/insights-section.tsx b/src/components/settings/insights-section.tsx index aee780b3a..73da8d53d 100644 --- a/src/components/settings/insights-section.tsx +++ b/src/components/settings/insights-section.tsx @@ -2,6 +2,7 @@ import { InsightsOverviewArrangeSection } from "@/components/settings/insights-overview-arrange-section"; import { InsightsPillOrderSection } from "@/components/settings/insights-pill-order-section"; +import { SettingsHubBackLink } from "@/components/settings/settings-hub-back-link"; import { useTranslations } from "@/lib/i18n/context"; /** @@ -23,7 +24,11 @@ export function InsightsSection() { aria-labelledby="settings-section-insights-title" className="space-y-6" > -
+
+

{t("settings.sections.insights.title")}

diff --git a/src/components/settings/medications-section.tsx b/src/components/settings/medications-section.tsx index 7e4830cf8..224d0817a 100644 --- a/src/components/settings/medications-section.tsx +++ b/src/components/settings/medications-section.tsx @@ -8,6 +8,7 @@ import { type ReorderMedication, } from "@/components/medications/medication-order-editor"; import { MedicationViewToggle } from "@/components/medications/medication-view-toggle"; +import { SettingsHubBackLink } from "@/components/settings/settings-hub-back-link"; import { apiGet } from "@/lib/api/api-fetch"; import { useTranslations } from "@/lib/i18n/context"; import { applyMedicationOrder } from "@/lib/medications/medication-order"; @@ -68,7 +69,11 @@ export function MedicationsSection() { aria-labelledby="settings-section-medications-title" className="space-y-6" > -
+
+

{t("settings.sections.medications.title")}

diff --git a/src/components/settings/mood-section.tsx b/src/components/settings/mood-section.tsx index d8a82248e..675a75547 100644 --- a/src/components/settings/mood-section.tsx +++ b/src/components/settings/mood-section.tsx @@ -6,6 +6,7 @@ import { ArchivedTagsCard } from "@/components/mood/manage/archived-tags-card"; import { TagGroupsCard } from "@/components/mood/manage/tag-groups-card"; import { TagManagerCard } from "@/components/mood/manage/tag-manager-card"; import { useMoodTagManage } from "@/components/mood/manage/use-mood-tag-manage"; +import { SettingsHubBackLink } from "@/components/settings/settings-hub-back-link"; import { useAuth } from "@/hooks/use-auth"; import { useTranslations } from "@/lib/i18n/context"; @@ -44,7 +45,11 @@ export function MoodSection() { aria-labelledby="settings-section-mood-title" className="space-y-6" > -
+
+

{t("settings.sections.mood.title")}

diff --git a/src/components/settings/settings-hub-back-link.tsx b/src/components/settings/settings-hub-back-link.tsx new file mode 100644 index 000000000..2f1933ca4 --- /dev/null +++ b/src/components/settings/settings-hub-back-link.tsx @@ -0,0 +1,39 @@ +"use client"; + +import Link from "next/link"; +import { ChevronLeft } from "lucide-react"; + +import { cn } from "@/lib/utils"; +import { useTranslations } from "@/lib/i18n/context"; + +/** + * v1.17.1 (N-5) — the up-affordance for a hub child editor. + * + * The four Layout personalization editors (dashboard / insights / + * medications / mood) are reached through the "Layout & Personalization" + * hub (or a page-header cog), and the left rail highlights the hub while + * the body shows the child. The return path existed only implicitly (tap + * the highlighted rail entry); this is the explicit "← back to hub" link + * at the top of the child, so the hub → child → hub loop reads clearly, + * especially on mobile where the rail collapses to a chip strip. + */ +export function SettingsHubBackLink({ + href, + labelKey, +}: { + href: string; + labelKey: string; +}) { + const { t } = useTranslations(); + return ( + +