Skip to content

Commit 34cf1cb

Browse files
authored
Extract settings page content rendering
Generated-By: PostHog Code Task-Id: 5579dbc2-d5dd-440f-8fb5-3cbd00ed0957
1 parent 4099fc1 commit 34cf1cb

2 files changed

Lines changed: 196 additions & 179 deletions

File tree

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
import { McpServersView } from "@posthog/ui/features/mcp-servers/components/McpServersView";
2+
import { AdvancedSettings } from "@posthog/ui/features/settings/sections/AdvancedSettings";
3+
import { AgentsSettings } from "@posthog/ui/features/settings/sections/AgentsSettings";
4+
import { ClaudeCodeSettings } from "@posthog/ui/features/settings/sections/ClaudeCodeSettings";
5+
import { DiscordSettings } from "@posthog/ui/features/settings/sections/DiscordSettings";
6+
import { EnvironmentsSettings } from "@posthog/ui/features/settings/sections/environments/EnvironmentsSettings";
7+
import { GeneralSettings } from "@posthog/ui/features/settings/sections/GeneralSettings";
8+
import { GitHubSettings } from "@posthog/ui/features/settings/sections/GitHubSettings";
9+
import { NotificationsSettings } from "@posthog/ui/features/settings/sections/NotificationsSettings";
10+
import { PersonalizationSettings } from "@posthog/ui/features/settings/sections/PersonalizationSettings";
11+
import { PlanUsageSettings } from "@posthog/ui/features/settings/sections/PlanUsageSettings";
12+
import { ShortcutsSettings } from "@posthog/ui/features/settings/sections/ShortcutsSettings";
13+
import { SignalSourcesSettings } from "@posthog/ui/features/settings/sections/SignalSourcesSettings";
14+
import { SlackSettings } from "@posthog/ui/features/settings/sections/SlackSettings";
15+
import { TerminalSettings } from "@posthog/ui/features/settings/sections/TerminalSettings";
16+
import { UpdatesSettings } from "@posthog/ui/features/settings/sections/UpdatesSettings";
17+
import { WorkspacesSettings } from "@posthog/ui/features/settings/sections/WorkspacesSettings";
18+
import { WorktreesSettings } from "@posthog/ui/features/settings/sections/worktrees/WorktreesSettings";
19+
import type { SettingsCategory } from "@posthog/ui/features/settings/types";
20+
import { SkillsView } from "@posthog/ui/features/skills/SkillsView";
21+
import { Box, Flex, ScrollArea, Text } from "@radix-ui/themes";
22+
import type { ComponentType, ReactNode } from "react";
23+
24+
const SETTINGS_PAGE_LAYOUT = {
25+
CONTAINED: "contained",
26+
FULL_BLEED: "full-bleed",
27+
} as const;
28+
29+
type SettingsPageLayout =
30+
(typeof SETTINGS_PAGE_LAYOUT)[keyof typeof SETTINGS_PAGE_LAYOUT];
31+
32+
interface SettingsPageDefinition {
33+
title: string;
34+
component: ComponentType;
35+
layout: SettingsPageLayout;
36+
}
37+
38+
function defineSettingsPage(
39+
title: string,
40+
component: ComponentType,
41+
layout: SettingsPageLayout = SETTINGS_PAGE_LAYOUT.CONTAINED,
42+
): SettingsPageDefinition {
43+
return { title, component, layout };
44+
}
45+
46+
const SETTINGS_PAGES: Record<SettingsCategory, SettingsPageDefinition> = {
47+
general: defineSettingsPage("General", GeneralSettings),
48+
notifications: defineSettingsPage("Notifications", NotificationsSettings),
49+
"plan-usage": defineSettingsPage("Plan & usage", PlanUsageSettings),
50+
workspaces: defineSettingsPage("Workspaces", WorkspacesSettings),
51+
worktrees: defineSettingsPage("Worktrees", WorktreesSettings),
52+
environments: defineSettingsPage("Environments", EnvironmentsSettings),
53+
"cloud-environments": defineSettingsPage(
54+
"Environments",
55+
EnvironmentsSettings,
56+
),
57+
agents: defineSettingsPage("Agents", AgentsSettings),
58+
skills: defineSettingsPage(
59+
"Skills",
60+
SkillsView,
61+
SETTINGS_PAGE_LAYOUT.FULL_BLEED,
62+
),
63+
"mcp-servers": defineSettingsPage(
64+
"MCP servers",
65+
McpServersView,
66+
SETTINGS_PAGE_LAYOUT.FULL_BLEED,
67+
),
68+
personalization: defineSettingsPage(
69+
"Personalization",
70+
PersonalizationSettings,
71+
),
72+
terminal: defineSettingsPage("Terminal", TerminalSettings),
73+
"claude-code": defineSettingsPage("Claude Code", ClaudeCodeSettings),
74+
shortcuts: defineSettingsPage("Shortcuts", ShortcutsSettings),
75+
github: defineSettingsPage("GitHub", GitHubSettings),
76+
slack: defineSettingsPage("Slack integration", SlackSettings),
77+
discord: defineSettingsPage("Discord", DiscordSettings),
78+
// Slack notification config lives in the dedicated Slack section; the Signals
79+
// section links out to it rather than duplicating the controls.
80+
signals: defineSettingsPage("Self-driving", () => (
81+
<SignalSourcesSettings showSlackNotifications={false} />
82+
)),
83+
updates: defineSettingsPage("Updates", UpdatesSettings),
84+
advanced: defineSettingsPage("Advanced", AdvancedSettings),
85+
};
86+
87+
interface SettingsPageLayoutProps {
88+
children: ReactNode;
89+
formMode: boolean;
90+
icon?: ReactNode;
91+
title: string;
92+
}
93+
94+
function SettingsPageHeader({
95+
formMode,
96+
icon,
97+
title,
98+
bordered = false,
99+
}: Omit<SettingsPageLayoutProps, "children"> & { bordered?: boolean }) {
100+
if (formMode) return null;
101+
102+
return (
103+
<Flex
104+
align="center"
105+
gap="2"
106+
className={
107+
bordered ? "shrink-0 border-gray-5 border-b px-6 py-4" : undefined
108+
}
109+
>
110+
{icon && <span className="text-gray-10">{icon}</span>}
111+
<Text className="font-medium text-lg leading-6.5">{title}</Text>
112+
</Flex>
113+
);
114+
}
115+
116+
function ContainedSettingsPageLayout({
117+
children,
118+
formMode,
119+
icon,
120+
title,
121+
}: SettingsPageLayoutProps) {
122+
return (
123+
<ScrollArea className="h-full w-full">
124+
<Box p="6" mx="auto" className="relative z-[1] max-w-[800px]">
125+
<Flex direction="column" gap="4">
126+
<SettingsPageHeader formMode={formMode} icon={icon} title={title} />
127+
{children}
128+
</Flex>
129+
</Box>
130+
</ScrollArea>
131+
);
132+
}
133+
134+
function FullBleedSettingsPageLayout({
135+
children,
136+
formMode,
137+
icon,
138+
title,
139+
}: SettingsPageLayoutProps) {
140+
return (
141+
<Flex direction="column" className="relative z-[1] h-full min-h-0 w-full">
142+
<SettingsPageHeader
143+
bordered
144+
formMode={formMode}
145+
icon={icon}
146+
title={title}
147+
/>
148+
<div className="min-h-0 flex-1">{children}</div>
149+
</Flex>
150+
);
151+
}
152+
153+
const SETTINGS_PAGE_LAYOUT_COMPONENTS: Record<
154+
SettingsPageLayout,
155+
ComponentType<SettingsPageLayoutProps>
156+
> = {
157+
[SETTINGS_PAGE_LAYOUT.CONTAINED]: ContainedSettingsPageLayout,
158+
[SETTINGS_PAGE_LAYOUT.FULL_BLEED]: FullBleedSettingsPageLayout,
159+
};
160+
161+
interface SettingsPageContentProps {
162+
category: SettingsCategory;
163+
formMode: boolean;
164+
icon?: ReactNode;
165+
}
166+
167+
export function SettingsPageContent({
168+
category,
169+
formMode,
170+
icon,
171+
}: SettingsPageContentProps) {
172+
const page = SETTINGS_PAGES[category];
173+
const PageComponent = page.component;
174+
const PageLayout = SETTINGS_PAGE_LAYOUT_COMPONENTS[page.layout];
175+
176+
return (
177+
<PageLayout formMode={formMode} icon={icon} title={page.title}>
178+
<PageComponent />
179+
</PageLayout>
180+
);
181+
}

0 commit comments

Comments
 (0)