Skip to content

Commit 2804605

Browse files
committed
Extract shared FullScreenLayout and restyle auth pages
1 parent 23db5f7 commit 2804605

5 files changed

Lines changed: 450 additions & 293 deletions

File tree

apps/code/src/renderer/App.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { LoginTransition } from "@components/LoginTransition";
33
import { MainLayout } from "@components/MainLayout";
44
import { ScopeReauthPrompt } from "@components/ScopeReauthPrompt";
55
import { AuthScreen } from "@features/auth/components/AuthScreen";
6+
import { InviteCodeScreen } from "@features/auth/components/InviteCodeScreen";
67
import { useAuthStateValue } from "@features/auth/hooks/authQueries";
78
import { useAuthSession } from "@features/auth/hooks/useAuthSession";
89
import { OnboardingFlow } from "@features/onboarding/components/OnboardingFlow";
@@ -136,14 +137,8 @@ function App() {
136137
}),
137138
);
138139

139-
// If authenticated but no access, force back into onboarding at the invite-code step
140-
useEffect(() => {
141-
if (isAuthenticated && hasCodeAccess === false && hasCompletedOnboarding) {
142-
const store = useOnboardingStore.getState();
143-
store.resetOnboarding();
144-
store.setCurrentStep("invite-code");
145-
}
146-
}, [isAuthenticated, hasCodeAccess, hasCompletedOnboarding]);
140+
const needsInviteCode =
141+
isAuthenticated && hasCodeAccess === false && hasCompletedOnboarding;
147142

148143
// Handle transition into main app — only show the dark overlay if dark mode is active
149144
useEffect(() => {
@@ -190,6 +185,14 @@ function App() {
190185
);
191186
}
192187

188+
if (needsInviteCode) {
189+
return (
190+
<motion.div key="invite-code" initial={{ opacity: 1 }}>
191+
<InviteCodeScreen />
192+
</motion.div>
193+
);
194+
}
195+
193196
return (
194197
<motion.div
195198
key="main"
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { Lifebuoy } from "@phosphor-icons/react";
2+
import { Button, Flex, Theme } from "@radix-ui/themes";
3+
import phWordmark from "@renderer/assets/images/wordmark.svg";
4+
import phWordmarkWhite from "@renderer/assets/images/wordmark-white.svg";
5+
import { trpcClient } from "@renderer/trpc/client";
6+
import { useThemeStore } from "@stores/themeStore";
7+
import { EXTERNAL_LINKS } from "@utils/links";
8+
import type { ReactNode } from "react";
9+
import { DotPatternBackground } from "./DotPatternBackground";
10+
import { DraggableTitleBar } from "./DraggableTitleBar";
11+
12+
interface FullScreenLayoutProps {
13+
children: ReactNode;
14+
footerLeft?: ReactNode;
15+
footerRight?: ReactNode;
16+
}
17+
18+
export function FullScreenLayout({
19+
children,
20+
footerLeft,
21+
footerRight,
22+
}: FullScreenLayoutProps) {
23+
const isDarkMode = useThemeStore((state) => state.isDarkMode);
24+
25+
return (
26+
<Theme
27+
appearance={isDarkMode ? "dark" : "light"}
28+
accentColor={isDarkMode ? "yellow" : "orange"}
29+
radius="medium"
30+
>
31+
<Flex
32+
direction="column"
33+
height="100vh"
34+
style={{ position: "relative", overflow: "hidden" }}
35+
>
36+
<DraggableTitleBar />
37+
38+
<div
39+
style={{
40+
position: "absolute",
41+
inset: 0,
42+
backgroundColor: "var(--color-background)",
43+
}}
44+
/>
45+
<DotPatternBackground />
46+
47+
<Flex
48+
direction="column"
49+
flexGrow="1"
50+
style={{
51+
position: "relative",
52+
zIndex: 1,
53+
minHeight: 0,
54+
width: "100%",
55+
}}
56+
>
57+
<img
58+
src={isDarkMode ? phWordmarkWhite : phWordmark}
59+
alt="PostHog"
60+
style={{
61+
height: "40px",
62+
objectFit: "contain",
63+
alignSelf: "flex-start",
64+
marginLeft: 32,
65+
marginTop: "clamp(24px, 6vh, 80px)",
66+
flexShrink: 0,
67+
}}
68+
/>
69+
70+
<Flex
71+
direction="column"
72+
flexGrow="1"
73+
overflow="hidden"
74+
style={{ minHeight: 0 }}
75+
>
76+
{children}
77+
</Flex>
78+
79+
<Flex
80+
justify="between"
81+
style={{
82+
position: "absolute",
83+
bottom: 20,
84+
left: 32,
85+
right: 32,
86+
zIndex: 2,
87+
}}
88+
>
89+
{footerLeft ?? (
90+
<Button
91+
size="1"
92+
variant="ghost"
93+
color="gray"
94+
onClick={() =>
95+
trpcClient.os.openExternal.mutate({
96+
url: EXTERNAL_LINKS.discord,
97+
})
98+
}
99+
style={{ opacity: 0.5 }}
100+
>
101+
<Lifebuoy size={14} />
102+
Get support
103+
</Button>
104+
)}
105+
{footerRight ?? <div />}
106+
</Flex>
107+
</Flex>
108+
</Flex>
109+
</Theme>
110+
);
111+
}
Lines changed: 46 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,63 @@
1-
import { DraggableTitleBar } from "@components/DraggableTitleBar";
2-
import { ZenHedgehog } from "@components/ZenHedgehog";
3-
import { Flex, Theme } from "@radix-ui/themes";
4-
import codeLogo from "@renderer/assets/images/code.svg";
5-
import { useThemeStore } from "@stores/themeStore";
1+
import { FullScreenLayout } from "@components/FullScreenLayout";
2+
import { OnboardingHogTip } from "@features/onboarding/components/OnboardingHogTip";
3+
import { Flex, Text } from "@radix-ui/themes";
4+
import happyHog from "@renderer/assets/images/hedgehogs/happy-hog.png";
65
import { OAuthControls } from "./OAuthControls";
76

87
export function AuthScreen() {
9-
const isDarkMode = useThemeStore((state) => state.isDarkMode);
10-
118
return (
12-
<Theme
13-
appearance={isDarkMode ? "dark" : "light"}
14-
accentColor={isDarkMode ? "yellow" : "orange"}
15-
radius="medium"
16-
>
17-
<Flex height="100vh" style={{ position: "relative", overflow: "hidden" }}>
18-
<DraggableTitleBar />
19-
20-
{/* Background */}
21-
<div
22-
style={{
23-
position: "absolute",
24-
inset: 0,
25-
backgroundColor: "var(--color-background)",
26-
}}
27-
/>
28-
29-
{/* Right panel — zen hedgehog */}
9+
<FullScreenLayout>
10+
<Flex align="center" justify="center" height="100%" px="8">
3011
<Flex
12+
direction="column"
3113
align="center"
32-
justify="center"
3314
style={{
34-
position: "absolute",
35-
top: 0,
36-
right: 0,
37-
bottom: 0,
38-
width: "50%",
39-
backgroundColor: "var(--color-background)",
15+
width: "100%",
16+
maxWidth: 480,
17+
height: "100%",
18+
paddingTop: 24,
19+
paddingBottom: 40,
4020
}}
4121
>
42-
<ZenHedgehog />
43-
</Flex>
44-
45-
{/* Left side with card */}
46-
<Flex
47-
width="50%"
48-
align="center"
49-
justify="center"
50-
style={{ position: "relative", zIndex: 1 }}
51-
>
52-
{/* Auth card */}
5322
<Flex
5423
direction="column"
55-
gap="5"
56-
style={{
57-
position: "relative",
58-
width: "360px",
59-
padding: "32px",
60-
backgroundColor: "var(--color-panel-solid)",
61-
borderRadius: "16px",
62-
border: "1px solid var(--gray-4)",
63-
boxShadow:
64-
"0 8px 32px rgba(0, 0, 0, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04)",
65-
}}
24+
justify="center"
25+
align="center"
26+
style={{ flex: 1, minHeight: 0, width: "100%" }}
6627
>
67-
{/* Logo */}
68-
<img
69-
src={codeLogo}
70-
alt="PostHog"
71-
style={{
72-
height: "30px",
73-
objectFit: "contain",
74-
alignSelf: "center",
75-
}}
76-
/>
77-
78-
<OAuthControls />
28+
<Flex
29+
direction="column"
30+
align="start"
31+
gap="6"
32+
style={{ width: "100%" }}
33+
>
34+
<Flex direction="column" gap="5" style={{ width: "100%" }}>
35+
<Flex direction="column" gap="3" style={{ width: "100%" }}>
36+
<Flex direction="column" gap="4">
37+
<Flex direction="column" gap="2">
38+
<Text
39+
size="6"
40+
weight="bold"
41+
style={{ color: "var(--gray-12)", lineHeight: 1.3 }}
42+
>
43+
Sign in to PostHog
44+
</Text>
45+
<Text size="2" style={{ color: "var(--gray-11)" }}>
46+
Connect your PostHog account to continue.
47+
</Text>
48+
</Flex>
49+
<OAuthControls />
50+
<OnboardingHogTip
51+
hogSrc={happyHog}
52+
message="Welcome back. Let's get shipping."
53+
/>
54+
</Flex>
55+
</Flex>
56+
</Flex>
57+
</Flex>
7958
</Flex>
8059
</Flex>
81-
82-
{/* Right side - shows background */}
83-
<div style={{ width: "50%" }} />
8460
</Flex>
85-
</Theme>
61+
</FullScreenLayout>
8662
);
8763
}

0 commit comments

Comments
 (0)