Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
a2efee4
feat(onboarding): align signup page with Chrome Web Store voice
tsahimatsliah May 19, 2026
727c264
feat(onboarding): bold dark signup hero with live feed preview
tsahimatsliah May 19, 2026
d11b3b4
Merge branch 'main' into feat/onboarding-signup-cws-align
tsahimatsliah May 19, 2026
5e9b7c5
fix(onboarding): render signup hero from the real V1 funnel step
tsahimatsliah May 19, 2026
8c03e79
refactor(onboarding): strip signup hero to a single visual + form
tsahimatsliah May 19, 2026
209caac
feat(onboarding): animated feed mosaic behind the signup form
tsahimatsliah May 19, 2026
02d1ed6
refactor(onboarding): flatten signup form back over the moving mosaic
tsahimatsliah May 19, 2026
a4961cc
fix(onboarding): render hero on the bare auth path as well
tsahimatsliah May 19, 2026
57ba697
feat(onboarding): richer feed mosaic + bottom-radial form gradient
tsahimatsliah May 19, 2026
c188305
feat(onboarding): center-bottom form + text-forward feed cards
tsahimatsliah May 19, 2026
de5b6f3
feat(onboarding): calm aurora background, uniform ghost cards
tsahimatsliah May 19, 2026
a0fedf1
feat(onboarding): topic constellation background
tsahimatsliah May 19, 2026
64692b7
feat(onboarding): variant switcher + Squad Universe background
tsahimatsliah May 19, 2026
a870917
fix(onboarding): make variant switcher reliably clickable
tsahimatsliah May 19, 2026
33e7815
feat(onboarding): replace Squads with Knowledge Map (transit map) var…
tsahimatsliah May 19, 2026
cabc442
feat(onboarding): three polished, product-grade hero variants
tsahimatsliah May 19, 2026
1e8e069
feat(onboarding): add Desk variant with real product photo backdrop
tsahimatsliah May 19, 2026
9649abc
feat(onboarding): grid-style hero variants with real photos and faces
tsahimatsliah May 19, 2026
cc6ffc3
feat(onboarding): real-card grid, restore Tags, center halo, form layout
tsahimatsliah May 19, 2026
3a4715a
feat(onboarding): real source logos, white email CTA, corner footer/d…
tsahimatsliah May 19, 2026
28f4e0a
feat(onboarding): real explore feed data, stronger center halo, email…
tsahimatsliah May 19, 2026
03f215c
feat(onboarding): use the real ArticleGrid for explore feed background
tsahimatsliah May 19, 2026
a3628e8
feat(onboarding): increase gap between email CTA and login link
tsahimatsliah May 19, 2026
e469483
feat(onboarding): layer feed behind orbs, remove clickbait shield fro…
tsahimatsliah May 19, 2026
32202ef
feat(onboarding): stronger orb glow, dim feed cards to 72%
tsahimatsliah May 19, 2026
268b3d1
fix(onboarding): merge main, resolve conflicts, ship split/X variant
tsahimatsliah May 20, 2026
0bf18d0
fix(onboarding): make variant switcher clickable, narrow signup to 340px
tsahimatsliah May 20, 2026
cc3d9ec
fix(onboarding): center X split signup block in right column
tsahimatsliah May 20, 2026
311dc78
feat(onboarding): X split signup copy and Sign in button section
tsahimatsliah May 20, 2026
d1c226a
fix(onboarding): X left column layout, restore feed actions, smaller …
tsahimatsliah May 20, 2026
48b9ed1
fix(onboarding): smaller headline, 360px column, unified X right panel
tsahimatsliah May 20, 2026
e236571
chore(onboarding): update desk variant hero background image
tsahimatsliah May 20, 2026
178d931
fix(onboarding): place X signup column in right grid half like Twitter
tsahimatsliah May 20, 2026
32e7ac5
fix(onboarding): sharper desk hero with WebP srcset and progressive load
tsahimatsliah May 20, 2026
6ef7a25
fix(onboarding): confine X variant blue glow to left column bottom
tsahimatsliah May 20, 2026
d0c4591
fix(onboarding): desk variant contrast, footer order, sharper hero asset
tsahimatsliah May 20, 2026
6528f70
fix(onboarding): desk variant adds form halo and sharper hero assets
tsahimatsliah May 20, 2026
74c1a6d
fix(onboarding): desk variant uses native-res WebP with full overlay …
tsahimatsliah May 20, 2026
bb39729
chore: re-trigger preview build
tsahimatsliah May 20, 2026
564bc30
fix(onboarding): high-res responsive desk hero WebPs
tsahimatsliah May 20, 2026
744239f
chore(onboarding): remove tags variant from hero switcher
tsahimatsliah May 20, 2026
b0c78b8
feat(onboarding): add prod-image toggle to hero variant switcher
tsahimatsliah May 20, 2026
fd8abed
feat(onboarding): three-way image mode (original/prod/colors) for sig…
tsahimatsliah May 20, 2026
413a3a6
fix(onboarding): make prod image actually visible by replacing heavy …
tsahimatsliah May 20, 2026
a5b65af
fix(onboarding): keep prod image in DOM with opacity toggle to ensure…
tsahimatsliah May 20, 2026
842fdd0
fix(onboarding): inline prod image URL to avoid potential lazy module…
tsahimatsliah May 20, 2026
f14d5e8
fix(onboarding): swap prod image to actual signup wall artwork
tsahimatsliah May 20, 2026
e54d63a
fix(onboarding): mobile layout polish for signup hero
tsahimatsliah May 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/shared/src/components/auth/AuthOptionsInner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ function AuthOptionsInner({
onboardingSignupButton,
hideLoginLink,
compact,
splitSignupStyle,
autoTriggerProvider,
socialProviderScopes,
}: AuthOptionsProps): ReactElement {
Expand Down Expand Up @@ -765,6 +766,7 @@ function AuthOptionsInner({
onboardingSignupButton={onboardingSignupButton}
hideLoginLink={hideLoginLink}
compact={compact}
splitSignupStyle={splitSignupStyle}
/>
</Tab>
<Tab label={AuthDisplay.SignBack}>
Expand Down
151 changes: 117 additions & 34 deletions packages/shared/src/components/auth/OnboardingRegistrationForm.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { ReactElement } from 'react';
import React, { useEffect } from 'react';
import classNames from 'classnames';
import type { AuthFormProps } from './common';
import { providerMap } from './common';
import OrDivider from './OrDivider';
import { useLogContext } from '../../contexts/LogContext';
import type { AuthTriggersType } from '../../lib/auth';
import { AuthEventNames } from '../../lib/auth';
import { AuthEventNames, AuthTriggers } from '../../lib/auth';
import type { ButtonProps } from '../buttons/Button';
import { Button, ButtonSize, ButtonVariant } from '../buttons/Button';
import { isIOSNative } from '../../lib/func';
Expand Down Expand Up @@ -36,6 +37,7 @@ interface OnboardingRegistrationFormProps extends AuthFormProps {
onboardingSignupButton?: ButtonProps<'button'>;
hideLoginLink?: boolean;
compact?: boolean;
splitSignupStyle?: boolean;
}

export const isWebView = (): boolean => {
Expand Down Expand Up @@ -87,14 +89,17 @@ export const isWebView = (): boolean => {
return isInAppBrowser || advancedInAppDetection();
};

const getSignupProviders = () => {
const getSignupProviders = (preferGithub: boolean) => {
if (isIOSNative()) {
return [providerMap.google, providerMap.apple];
}
if (isWebView()) {
return [providerMap.github];
}
return [providerMap.google, providerMap.github];
// Developer-first audiences convert better when GitHub leads the OAuth list.
return preferGithub
? [providerMap.github, providerMap.google]
: [providerMap.google, providerMap.github];
};

export const OnboardingRegistrationForm = ({
Expand All @@ -108,8 +113,10 @@ export const OnboardingRegistrationForm = ({
onboardingSignupButton,
hideLoginLink,
compact,
splitSignupStyle = false,
}: OnboardingRegistrationFormProps): ReactElement => {
const { logEvent } = useLogContext();
const isOnboardingTrigger = trigger === AuthTriggers.Onboarding;

const trackOpenSignup = () => {
logEvent({
Expand All @@ -130,13 +137,97 @@ export const OnboardingRegistrationForm = ({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const tertiarySignupButtonClass =
'!w-full !border !border-border-subtlest-tertiary !text-white';

const getEmailButtonClass = (): string => {
if (compact) {
return 'mb-4';
}
if (isOnboardingTrigger && !splitSignupStyle) {
return 'mb-3';
}
return 'mb-8';
};

const emailButtonLabel = splitSignupStyle
? 'Create account'
: 'Continue with email';

const emailButton = (
<Button
aria-label={splitSignupStyle ? 'Create account' : 'Signup using email'}
className={classNames(
getEmailButtonClass(),
(isOnboardingTrigger || splitSignupStyle) && tertiarySignupButtonClass,
)}
data-funnel-track={FunnelTargetId.SignupProvider}
disabled={isSocialAuthLoading}
onClick={() => {
trackOpenSignup();
onContinueWithEmail?.();
}}
size={onboardingSignupButton?.size ?? ButtonSize.Large}
type="button"
variant={
isOnboardingTrigger || splitSignupStyle
? ButtonVariant.Tertiary
: ButtonVariant.Float
}
>
{emailButtonLabel}
</Button>
);

const getMemberAlreadyContainerClass = (): string => {
if (isOnboardingTrigger) {
return 'mx-auto mt-5 text-center text-text-secondary typo-callout';
}
return 'mx-auto mt-6 text-center text-text-secondary typo-callout';
};

const memberAlready = !hideLoginLink && !splitSignupStyle && (
<MemberAlready
onLogin={() => onExistingEmail?.('')}
className={{
container: getMemberAlreadyContainerClass(),
login: '!text-inherit',
}}
/>
);

const splitSignInSection = splitSignupStyle && !hideLoginLink && (
<div className="mt-2 flex w-full flex-col items-start gap-3">
<p className="text-left text-text-secondary typo-callout">
Already have an account?
</p>
<Button
aria-label="Sign in"
className={tertiarySignupButtonClass}
onClick={() => onExistingEmail?.('')}
size={onboardingSignupButton?.size ?? ButtonSize.Large}
type="button"
variant={ButtonVariant.Tertiary}
>
Sign in
</Button>
</div>
);
const disclaimer = (
<SignupDisclaimer className="!text-text-tertiary tablet:!typo-footnote" />
);

return (
<div aria-label="Login/Register options" className="flex flex-col gap-4">
<ul aria-label="Social login buttons" className="flex flex-col gap-4">
{getSignupProviders().map((provider) => (
{getSignupProviders(isOnboardingTrigger).map((provider) => (
<li key={provider.value}>
<Button
aria-label={`Continue with ${provider.label}`}
aria-label={
splitSignupStyle
? `Sign up with ${provider.label}`
: `Continue with ${provider.label}`
}
className="w-full"
data-funnel-track={FunnelTargetId.SignupProvider}
disabled={!isReady || isSocialAuthLoading}
Expand All @@ -147,7 +238,9 @@ export const OnboardingRegistrationForm = ({
type="button"
variant={onboardingSignupButton?.variant ?? ButtonVariant.Primary}
>
Continue with {provider.label}
{splitSignupStyle
? `Sign up with ${provider.label}`
: `Continue with ${provider.label}`}
</Button>
</li>
))}
Expand All @@ -156,36 +249,26 @@ export const OnboardingRegistrationForm = ({
className={{
text: 'text-text-tertiary typo-footnote',
}}
label="OR"
label={isOnboardingTrigger ? 'or' : 'OR'}
/>
<div className="flex flex-col-reverse text-center">
{!hideLoginLink && (
<MemberAlready
onLogin={() => onExistingEmail?.('')}
className={{
container:
'mx-auto mt-6 text-center text-text-secondary typo-callout',
login: '!text-inherit',
}}
/>
)}
<SignupDisclaimer className="!text-text-tertiary tablet:!typo-footnote" />
<Button
aria-label="Signup using email"
className={compact ? 'mb-4' : 'mb-8'}
data-funnel-track={FunnelTargetId.SignupProvider}
disabled={isSocialAuthLoading}
onClick={() => {
trackOpenSignup();
onContinueWithEmail?.();
}}
size={onboardingSignupButton?.size ?? ButtonSize.Large}
type="button"
variant={ButtonVariant.Float}
{isOnboardingTrigger ? (
<div
className={classNames(
'flex flex-col',
splitSignupStyle ? 'items-start text-left' : 'text-center',
)}
>
Continue with email
</Button>
</div>
{emailButton}
{splitSignInSection}
{memberAlready}
</div>
) : (
<div className="flex flex-col-reverse text-center">
{memberAlready}
{disclaimer}
{emailButton}
</div>
)}
</div>
);
};
Expand Down
2 changes: 2 additions & 0 deletions packages/shared/src/components/auth/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ export interface AuthOptionsProps {
onboardingSignupButton?: ButtonProps<'button'>;
hideLoginLink?: boolean;
compact?: boolean;
/** X-style split onboarding: "Sign up with", "Create account", Sign in button */
splitSignupStyle?: boolean;
autoTriggerProvider?: string;
socialProviderScopes?: string[];
}
Loading
Loading