Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion packages/shared/src/components/auth/AuthOptionsInner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ function AuthOptionsInner({
simplified = false,
ignoreMessages = false,
onboardingSignupButton,
hideLoginLink,
compact,
autoTriggerProvider,
socialProviderScopes,
}: AuthOptionsProps): ReactElement {
Expand Down Expand Up @@ -681,7 +683,7 @@ function AuthOptionsInner({
className={classNames(
'z-1 flex w-full max-w-[26.25rem] flex-col overflow-y-auto rounded-16',
!simplified && 'bg-accent-pepper-subtlest',
defaultDisplay === AuthDisplay.OnboardingSignup
defaultDisplay === AuthDisplay.OnboardingSignup && !compact
? 'min-h-[21.25rem]'
: undefined,
className?.container,
Expand Down Expand Up @@ -786,6 +788,8 @@ function AuthOptionsInner({
targetId={targetId}
className={className}
onboardingSignupButton={onboardingSignupButton}
hideLoginLink={hideLoginLink}
compact={compact}
/>
</Tab>
<Tab label={AuthDisplay.SignBack}>
Expand Down
33 changes: 20 additions & 13 deletions packages/shared/src/components/auth/OnboardingRegistrationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ interface OnboardingRegistrationFormProps extends AuthFormProps {
isSocialAuthLoading?: boolean;
className?: ClassName;
onboardingSignupButton?: ButtonProps<'button'>;
hideLoginLink?: boolean;
compact?: boolean;
}

export const isWebView = (): boolean => {
Expand Down Expand Up @@ -105,6 +107,9 @@ export const OnboardingRegistrationForm = ({
onProviderClick,
targetId,
trigger,
onboardingSignupButton,
hideLoginLink,
compact,
}: OnboardingRegistrationFormProps): ReactElement => {
const { logEvent } = useLogContext();
const { value: isOnboardingV2 } = useConditionalFeature({
Expand Down Expand Up @@ -144,9 +149,9 @@ export const OnboardingRegistrationForm = ({
icon={provider.icon}
loading={!isReady || isSocialAuthLoading}
onClick={() => onProviderClick?.(provider.value, false)}
size={ButtonSize.Large}
size={onboardingSignupButton?.size ?? ButtonSize.Large}
type="button"
variant={ButtonVariant.Primary}
variant={onboardingSignupButton?.variant ?? ButtonVariant.Primary}
>
Continue with {provider.label}
</Button>
Expand All @@ -160,26 +165,28 @@ export const OnboardingRegistrationForm = ({
label="OR"
/>
<div className="flex flex-col-reverse text-center">
<MemberAlready
onLogin={() => onExistingEmail?.('')}
className={{
container: isOnboardingV2
? 'mx-auto mt-6 w-full justify-center border-t border-border-subtlest-tertiary pt-6 text-center text-text-secondary typo-callout'
: 'mx-auto mt-6 text-center text-text-secondary typo-callout',
login: '!text-inherit',
}}
/>
{!hideLoginLink && (
<MemberAlready
onLogin={() => onExistingEmail?.('')}
className={{
container: isOnboardingV2
? 'mx-auto mt-6 w-full justify-center border-t border-border-subtlest-tertiary pt-6 text-center text-text-secondary typo-callout'
: '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="mb-8"
className={compact ? 'mb-4' : 'mb-8'}
data-funnel-track={FunnelTargetId.SignupProvider}
disabled={isSocialAuthLoading}
onClick={() => {
trackOpenSignup();
onContinueWithEmail?.();
}}
size={ButtonSize.Large}
size={onboardingSignupButton?.size ?? ButtonSize.Large}
type="button"
variant={ButtonVariant.Float}
>
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 @@ -130,6 +130,8 @@ export interface AuthOptionsProps {
targetId?: string;
ignoreMessages?: boolean;
onboardingSignupButton?: ButtonProps<'button'>;
hideLoginLink?: boolean;
compact?: boolean;
autoTriggerProvider?: string;
socialProviderScopes?: string[];
}
76 changes: 76 additions & 0 deletions packages/shared/src/components/post/PostSignupWidget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import type { ReactElement } from 'react';
import React from 'react';
import { useAuthContext } from '../../contexts/AuthContext';
import { useConditionalFeature } from '../../hooks/useConditionalFeature';
import { featurePostSignupWidget } from '../../lib/featureManagement';
import { AuthTriggers } from '../../lib/auth';
import { ButtonSize, ButtonVariant } from '../buttons/Button';
import AuthOptions from '../auth/AuthOptions';
import { AuthDisplay } from '../auth/common';

const gradientStyle: React.CSSProperties = {
backgroundImage:
'linear-gradient(90deg, var(--theme-accent-cabbage-default) 0%, var(--theme-accent-onion-default) 30%, var(--theme-accent-water-default) 60%, var(--theme-accent-cabbage-default) 100%)',
backgroundSize: '200% auto',
animation: 'post-signup-gradient-shift 10s ease-in-out infinite',
WebkitBackgroundClip: 'text',
backgroundClip: 'text',
color: 'transparent',
};

export function PostSignupWidget(): ReactElement | null {
const { user, isAuthReady, showLogin } = useAuthContext();
const shouldEvaluate = isAuthReady && !user;
const { value: isEnabled } = useConditionalFeature({
feature: featurePostSignupWidget,
shouldEvaluate,
});

if (!shouldEvaluate || !isEnabled) {
return null;
}

return (
<div className="flex flex-col rounded-16 border border-border-subtlest-tertiary p-4">
<style>
{`@keyframes post-signup-gradient-shift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}`}
</style>
<h3 className="font-bold typo-title3" style={gradientStyle}>
Want your personalized dev feed?
</h3>
<p className="mt-2 text-text-tertiary typo-footnote">
Millions of developers rely on daily.dev for tech news, tools, and
discussions that actually matter.
</p>
<div className="mt-4">
<AuthOptions
ignoreMessages
formRef={null as unknown as React.MutableRefObject<HTMLFormElement>}
trigger={AuthTriggers.PostPage}
simplified
defaultDisplay={AuthDisplay.OnboardingSignup}
forceDefaultDisplay
className={{
onboardingSignup: '!gap-3',
}}
onAuthStateUpdate={(props) => {
showLogin({
trigger: AuthTriggers.Onboarding,
options: { isLogin: true, formValues: props },
});
}}
onboardingSignupButton={{
variant: ButtonVariant.Primary,
size: ButtonSize.Medium,
}}
hideLoginLink
compact
/>
</div>
</div>
);
}
2 changes: 2 additions & 0 deletions packages/shared/src/components/post/PostWidgets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { SourceType } from '../../graphql/sources';
import EntityCardSkeleton from '../cards/entity/EntityCardSkeleton';
import { PostSidebarAdWidget } from './PostSidebarAdWidget';
import { FeaturedArchives } from '../widgets/FeaturedArchives';
import { PostSignupWidget } from './PostSignupWidget';

const UserEntityCard = dynamic(
/* webpackChunkName: "userEntityCard" */ () =>
Expand Down Expand Up @@ -81,6 +82,7 @@ export function PostWidgets({

return (
<PageWidgets className={className}>
<PostSignupWidget />
{sourceCard}
{creator && (
<UserEntityCard
Expand Down
2 changes: 2 additions & 0 deletions packages/shared/src/components/post/SquadPostWidgets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import UserEntityCard from '../cards/entity/UserEntityCard';
import type { UserShortProfile } from '../../lib/user';
import { PostSidebarAdWidget } from './PostSidebarAdWidget';
import { FeaturedArchives } from '../widgets/FeaturedArchives';
import { PostSignupWidget } from './PostSignupWidget';

export function SquadPostWidgets({
onCopyPostLink,
Expand All @@ -34,6 +35,7 @@ export function SquadPostWidgets({

return (
<PageWidgets className={className}>
<PostSignupWidget />
{!isUserSource &&
(isSquadSource ? (
<SquadEntityCard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { PostWidgetsProps } from '../PostWidgets';
import { FooterLinks } from '../../footer';
import { PostSidebarAdWidget } from '../PostSidebarAdWidget';
import { FeaturedArchives } from '../../widgets/FeaturedArchives';
import { PostSignupWidget } from '../PostSignupWidget';

export const CollectionPostWidgets = ({
onCopyPostLink,
Expand All @@ -19,6 +20,7 @@ export const CollectionPostWidgets = ({
}: PostWidgetsProps): ReactElement => {
return (
<PageWidgets className={className}>
<PostSignupWidget />
<CollectionsIntro className="hidden laptop:flex" />
<RelatedPostsWidget
post={post}
Expand Down
1 change: 1 addition & 0 deletions packages/shared/src/lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export enum AuthTriggers {
RecruiterSelfServe = 'recruiter self serve',
AiFluencyQuiz = 'ai fluency quiz',
Gear = 'gear',
PostPage = 'post page',
}

export type AuthTriggersType =
Expand Down
2 changes: 2 additions & 0 deletions packages/shared/src/lib/featureManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,5 @@ export const sharedPostPreviewFeature = new Feature(
);

export const featureOnboardingV2 = new Feature('onboarding_v2', false);

export const featurePostSignupWidget = new Feature('post_signup_widget', false);
10 changes: 9 additions & 1 deletion packages/webapp/pages/posts/[id]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import classNames from 'classnames';
import { useOnboardingActions } from '@dailydotdev/shared/src/hooks/auth/useOnboardingActions';
import { webappUrl } from '@dailydotdev/shared/src/lib/constants';
import { useFeatureTheme } from '@dailydotdev/shared/src/hooks/utils/useFeatureTheme';
import { useConditionalFeature } from '@dailydotdev/shared/src/hooks/useConditionalFeature';
import { featurePostSignupWidget } from '@dailydotdev/shared/src/lib/featureManagement';
import CustomAuthBanner from '@dailydotdev/shared/src/components/auth/CustomAuthBanner';
import { isSourceUserSource } from '@dailydotdev/shared/src/graphql/sources';
import { usePostReferrerContext } from '@dailydotdev/shared/src/contexts/PostReferrerContext';
Expand Down Expand Up @@ -183,6 +185,10 @@ export const PostPage = ({
const isFallback = false;
const { shouldShowAuthBanner } = useOnboardingActions();
const isLaptop = useViewSize(ViewSize.Laptop);
const { value: isPostSignupWidget } = useConditionalFeature({
feature: featurePostSignupWidget,
shouldEvaluate: shouldShowAuthBanner,
});
const { post, isError, isLoading } = usePostById({
id,
options: {
Expand Down Expand Up @@ -282,7 +288,9 @@ export const PostPage = ({
},
}}
/>
{shouldShowAuthBanner && isLaptop && <PostAuthBanner />}
{shouldShowAuthBanner && isLaptop && !isPostSignupWidget && (
<PostAuthBanner />
)}
</FooterNavBarLayout>
</LogExtraContextProvider>
</ActivePostContextProvider>
Expand Down
Loading