Skip to content

Commit a0c76cc

Browse files
committed
chore: update document titles to use <title> tags
1 parent ac2461d commit a0c76cc

File tree

15 files changed

+79
-0
lines changed

15 files changed

+79
-0
lines changed

frontend/src/components/explorer/thematicContent.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export function ThematicContent() {
4040
const themeObj = themes.find((t) => t.name === theme);
4141
return (
4242
<>
43+
<title>{`${themeObj?.title} Explorer - Climate REF`}</title>
4344
<div className="space-x-2">
4445
{themes.map((item) => (
4546
<Link
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { useMatches } from "@tanstack/react-router";
2+
import { useEffect, useState } from "react";
3+
4+
const BASE_TITLE = "Climate REF";
5+
6+
/**
7+
* Hook that updates the document title based on the current route's staticData.
8+
* Uses route matches to find the most specific title in the route hierarchy.
9+
* Returns the current title for use with React's <title> component.
10+
*
11+
* For dynamic titles, you can still use <title> which will override this hook.
12+
*/
13+
export function useDocumentTitle() {
14+
const matches = useMatches();
15+
const [title, setTitle] = useState(BASE_TITLE);
16+
17+
useEffect(() => {
18+
// Find the most specific route with a title in staticData
19+
// Iterate from the end (most specific) to start (least specific)
20+
for (let i = matches.length - 1; i >= 0; i--) {
21+
const match = matches[i];
22+
const routeTitle = match?.staticData?.title;
23+
24+
if (routeTitle && typeof routeTitle === "string") {
25+
const fullTitle = `${routeTitle} - ${BASE_TITLE}`;
26+
setTitle(fullTitle);
27+
return;
28+
}
29+
}
30+
31+
// If no title found, use base title
32+
setTitle(BASE_TITLE);
33+
}, [matches]);
34+
35+
return title;
36+
}

frontend/src/routes/__root.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Footer } from "@/components/app/footer";
1111
import { Navbar } from "@/components/app/navbar.tsx";
1212
import { WelcomeModal } from "@/components/app/welcomeModal";
1313
import { useApiEndpoint } from "@/hooks/useApiEndpoint";
14+
import { useDocumentTitle } from "@/hooks/useDocumentTitle";
1415

1516
// Initialize Plausible Analytics
1617
init({
@@ -23,6 +24,7 @@ init({
2324

2425
function AppLayout() {
2526
const { isUsingOverride } = useApiEndpoint();
27+
const title = useDocumentTitle();
2628
return (
2729
<ErrorBoundary
2830
fallback={
@@ -49,6 +51,7 @@ function AppLayout() {
4951
});
5052
}}
5153
>
54+
<title>{title}</title>
5255
<Navbar />
5356
<ErrorBoundary
5457
fallback={<ErrorFallback title="Page Error" showHomeButton={true} />}

frontend/src/routes/_app/datasets.$slug.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createFileRoute } from "@tanstack/react-router";
2+
import { useEffect } from "react";
23
import type { ExecutionGroup } from "@/client";
34
import {
45
datasetsExecutionsOptions,
@@ -31,6 +32,9 @@ export const Route = createFileRoute("/_app/datasets/$slug")({
3132
return { dataset, executions };
3233
},
3334
component: DatasetPage,
35+
staticData: {
36+
title: "Dataset Details",
37+
},
3438
errorComponent: ({ error }) => {
3539
return <div>Error: {error.message}</div>;
3640
},
@@ -43,6 +47,7 @@ function DatasetPage() {
4347

4448
return (
4549
<div className="container mx-auto p-4">
50+
<title>{`${ds.slug} - Climate REF`}</title>
4651
<DetailsPanel
4752
title={ds.slug}
4853
description={ds.dataset_type}

frontend/src/routes/_app/datasets.index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ const DatasetsSearchSchema = z.object({
2626
export const Route = createFileRoute("/_app/datasets/")({
2727
component: SourcesIndexPage,
2828
validateSearch: zodValidator(DatasetsSearchSchema),
29+
staticData: {
30+
title: "Datasets",
31+
},
2932
loader: async ({ context: { queryClient } }) => {
3033
return queryClient.ensureQueryData(datasetsListOptions());
3134
},

frontend/src/routes/_app/diagnostics.$providerSlug.$diagnosticSlug/figures.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const Figures = () => {
77
const { providerSlug, diagnosticSlug } = Route.useParams();
88
return (
99
<div className="space-y-4">
10+
<title>{`Figures - ${diagnosticSlug} - Climate REF`}</title>
1011
<Card>
1112
<CardHeader>
1213
<CardTitle>Figures Gallery</CardTitle>

frontend/src/routes/_app/diagnostics.$providerSlug.$diagnosticSlug/groups.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,7 @@ export const Route = createFileRoute(
1818
"/_app/diagnostics/$providerSlug/$diagnosticSlug/groups",
1919
)({
2020
component: Executions,
21+
staticData: {
22+
title: "Execution Groups",
23+
},
2124
});

frontend/src/routes/_app/diagnostics.$providerSlug.$diagnosticSlug/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { createFileRoute, redirect } from "@tanstack/react-router";
33
export const Route = createFileRoute(
44
"/_app/diagnostics/$providerSlug/$diagnosticSlug/",
55
)({
6+
staticData: {
7+
title: "Diagnostic Details",
8+
},
69
beforeLoad: ({ params }) => {
710
throw redirect({
811
to: "/diagnostics/$providerSlug/$diagnosticSlug/figures",

frontend/src/routes/_app/diagnostics.$providerSlug.$diagnosticSlug/route.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
useNavigate,
77
} from "@tanstack/react-router";
88
import { HelpCircle } from "lucide-react";
9+
import { useEffect } from "react";
910
import type { GroupBy, ReferenceDatasetLink } from "@/client";
1011
import { diagnosticsGetOptions } from "@/client/@tanstack/react-query.gen.ts";
1112
import { DiagnosticInfoSkeleton } from "@/components/diagnostics/diagnosticInfoSkeleton";
@@ -49,6 +50,7 @@ const DiagnosticInfoLayout = () => {
4950

5051
return (
5152
<div className="flex flex-col gap-4">
53+
<title>{`${data?.name} - Climate REF`}</title>
5254
<Card className="md:col-span-2">
5355
<CardHeader>
5456
<CardTitle className="mb-6">
@@ -362,6 +364,9 @@ export const Route = createFileRoute(
362364
component: DiagnosticInfoLayout,
363365
pendingComponent: DiagnosticInfoSkeleton,
364366
pendingMs: 200,
367+
staticData: {
368+
title: "Diagnostic Details",
369+
},
365370
loader: ({ context: { queryClient }, params }) => {
366371
return queryClient.ensureQueryData(
367372
diagnosticsGetOptions({

frontend/src/routes/_app/diagnostics.$providerSlug.$diagnosticSlug/scalars.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,7 @@ export const Route = createFileRoute(
8686
)({
8787
component: ScalarsValuesTab,
8888
validateSearch: zodValidator(valuesSearchSchema),
89+
staticData: {
90+
title: "Scalar Values",
91+
},
8992
});

0 commit comments

Comments
 (0)