diff --git a/apps/dashboard/src/components/issues/detail/issue-detail-page.tsx b/apps/dashboard/src/components/issues/detail/issue-detail-page.tsx index 906e6c5..923646b 100644 --- a/apps/dashboard/src/components/issues/detail/issue-detail-page.tsx +++ b/apps/dashboard/src/components/issues/detail/issue-detail-page.tsx @@ -15,6 +15,7 @@ import { import { githubRevalidationSignalKeys } from "#/lib/github-revalidation"; import { useGitHubSignalStream } from "#/lib/use-github-signal-stream"; import { useHasMounted } from "#/lib/use-has-mounted"; +import { usePageTitle } from "#/lib/use-page-title"; import { useRegisterTab } from "#/lib/use-register-tab"; import { IssueDetailActivitySection } from "./issue-detail-activity"; import { getIssueStateConfig, IssueDetailHeader } from "./issue-detail-header"; @@ -89,6 +90,8 @@ export function IssueDetailContent({ const commentPagination = pageQuery.data?.commentPagination; const eventPagination = pageQuery.data?.eventPagination; + usePageTitle(issue?.title); + useRegisterTab( registerTab && issue ? { diff --git a/apps/dashboard/src/components/pulls/detail/pull-detail-page.tsx b/apps/dashboard/src/components/pulls/detail/pull-detail-page.tsx index 5dd4db6..d84cee6 100644 --- a/apps/dashboard/src/components/pulls/detail/pull-detail-page.tsx +++ b/apps/dashboard/src/components/pulls/detail/pull-detail-page.tsx @@ -17,6 +17,7 @@ import { import { githubRevalidationSignalKeys } from "#/lib/github-revalidation"; import { useGitHubSignalStream } from "#/lib/use-github-signal-stream"; import { useHasMounted } from "#/lib/use-has-mounted"; +import { usePageTitle } from "#/lib/use-page-title"; import { useRegisterTab } from "#/lib/use-register-tab"; import { PullBodySection } from "./pull-body-section"; import { PullDetailActivitySection } from "./pull-detail-activity"; @@ -123,6 +124,8 @@ export function PullDetailContent({ const headRefDeleted = pageQuery.data?.headRefDeleted ?? false; const viewer = viewerQuery.data ?? null; + usePageTitle(pr?.title); + useRegisterTab( registerTab && pr ? { diff --git a/apps/dashboard/src/components/pulls/review/review-page.tsx b/apps/dashboard/src/components/pulls/review/review-page.tsx index 0e83c83..4404464 100644 --- a/apps/dashboard/src/components/pulls/review/review-page.tsx +++ b/apps/dashboard/src/components/pulls/review/review-page.tsx @@ -51,6 +51,7 @@ import type { } from "#/lib/github.types"; import { githubRevalidationSignalKeys } from "#/lib/github-revalidation"; import { useGitHubSignalStream } from "#/lib/use-github-signal-stream"; +import { usePageTitle } from "#/lib/use-page-title"; import { useRegisterTab } from "#/lib/use-register-tab"; import { checkPermissionWarning } from "#/lib/warning-store"; import type { ReviewDiffPaneHandle } from "./review-diff-pane"; @@ -220,6 +221,8 @@ export function ReviewPage() { ); const reviewComments = reviewCommentsQuery.data ?? []; + usePageTitle(pr ? `Review: ${pr.title}` : null); + // ── Mention support for inline comment forms ────────────────────── const [mentionActivated, setMentionActivated] = useState(false); const viewerQuery = useQuery(githubViewerQueryOptions(scope)); diff --git a/apps/dashboard/src/lib/seo.test.ts b/apps/dashboard/src/lib/seo.test.ts index 43495bc..3140fe4 100644 --- a/apps/dashboard/src/lib/seo.test.ts +++ b/apps/dashboard/src/lib/seo.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { buildSeo, summarizeText, toAbsoluteUrl } from "./seo"; +import { buildSeo, formatPageTitle, summarizeText, toAbsoluteUrl } from "./seo"; describe("summarizeText", () => { it("strips basic markdown and whitespace", () => { @@ -46,3 +46,13 @@ describe("buildSeo", () => { }); }); }); + +describe("formatPageTitle", () => { + it("adds the app name when it is missing", () => { + expect(formatPageTitle("Fix tab titles")).toBe("Fix tab titles | DiffKit"); + }); + + it("does not duplicate the app name", () => { + expect(formatPageTitle("Inbox | DiffKit")).toBe("Inbox | DiffKit"); + }); +}); diff --git a/apps/dashboard/src/lib/use-page-title.ts b/apps/dashboard/src/lib/use-page-title.ts new file mode 100644 index 0000000..89f5ce2 --- /dev/null +++ b/apps/dashboard/src/lib/use-page-title.ts @@ -0,0 +1,9 @@ +import { useEffect } from "react"; +import { formatPageTitle } from "./seo"; + +export function usePageTitle(title: string | null | undefined) { + useEffect(() => { + if (!title) return; + document.title = formatPageTitle(title); + }, [title]); +}