Skip to content

Commit a537f51

Browse files
committed
fix(webapp): keep the organization in the title on its own pages
1 parent e24e857 commit a537f51

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

apps/webapp/app/utils/pageTitle.test.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ describe("pageMeta", () => {
103103
).toBe("other | Tasks | Trigger.dev");
104104
});
105105

106-
it("keeps the app env tag", () => {
106+
it("names the organization on its own pages, with the app env tag", () => {
107107
const stagingRoot: Route = {
108108
id: "root",
109109
data: { appEnv: "staging" },
@@ -119,7 +119,7 @@ describe("pageMeta", () => {
119119
{ organizationSlug: "acme" }
120120
);
121121

122-
expect(title).toBe("Team | Trigger.dev (staging)");
122+
expect(title).toBe("Team | Acme | Trigger.dev (staging)");
123123
});
124124

125125
it("carries the root's non-title tags through", () => {
@@ -137,4 +137,11 @@ describe("pageMeta", () => {
137137
expect(descriptors).toContainEqual({ name: "viewport", content: "width=1024" });
138138
expect(renderTitle(routes)).toBe("Runs | Trigger.dev");
139139
});
140+
141+
it("does not name the organization inside a project", () => {
142+
// The dashboard switches projects in every tab at once, so the scope adds nothing there.
143+
expect(renderTitle([rootRoute, orgRoute, { id: "routes/runs", meta: pageMeta("Runs") }])).toBe(
144+
"Runs | Trigger.dev"
145+
);
146+
});
140147
});

apps/webapp/app/utils/pageTitle.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import { appEnvTitleTag } from "~/utils";
77
* is; the app title is added here.
88
*
99
* Shape (leading words carry the information, so a narrow tab still reads):
10-
* page: `Runs | Trigger.dev`
11-
* entity: `run_abc | Runs | Trigger.dev`
12-
* else: `Login to Trigger.dev` etc.
10+
* env page: `Runs | Trigger.dev`
11+
* env entity: `run_abc | Runs | Trigger.dev`
12+
* org page: `Team | Acme | Trigger.dev`
13+
* else: `Login to Trigger.dev` etc.
1314
*
1415
* Remix v2 picks the meta of the deepest route that exports one; a route without a meta export
1516
* inherits its nearest ancestor's. So a layout's `pageMeta` is the fallback for children that
@@ -19,6 +20,9 @@ import { appEnvTitleTag } from "~/utils";
1920

2021
const APP_NAME = "Trigger.dev";
2122

23+
/** The org route carries the organization the URL resolved to. */
24+
const ORGANIZATION_MATCH_ID = "routes/_app.orgs.$organizationSlug";
25+
2226
/** One or more title segments, most specific first: `["run_abc", "Runs"]`. */
2327
export type TitleSegments = string | string[];
2428

@@ -52,13 +56,24 @@ export function pageMeta<TLoader = unknown>(page: PageInput<TLoader>): MetaFunct
5256
};
5357
}
5458

55-
/** Builds the full title from the page segments plus the app title. */
59+
/** Builds the full title from the page segments, the org scope and the app title. */
5660
export function composePageTitle(segments: string[], matches: Matches): string {
57-
return [...segments, appTitle(appEnvFromMatches(matches))]
61+
return [...segments, scopeFromMatches(matches), appTitle(appEnvFromMatches(matches))]
5862
.filter((segment): segment is string => Boolean(segment))
5963
.join(" | ");
6064
}
6165

66+
/**
67+
* The organization, and only on its own pages: inside a project the tab is already about one
68+
* project, and the dashboard switches projects in every tab at once, so naming it adds nothing.
69+
*/
70+
export function scopeFromMatches(matches: Matches): string | undefined {
71+
const match = matches.find((m) => m.id === ORGANIZATION_MATCH_ID);
72+
if (!match || match.params?.projectParam) return undefined;
73+
const data = match.data as { organization?: { title?: string | null } } | undefined;
74+
return data?.organization?.title ?? undefined;
75+
}
76+
6277
function appEnvFromMatches(matches: Matches): string | undefined {
6378
const rootData = matches[0]?.data as { appEnv?: string } | undefined;
6479
return rootData?.appEnv;

0 commit comments

Comments
 (0)