Merge pull request #34060 from overleaf/oa-timeout-cta

[web] Compile timeout CTA

GitOrigin-RevId: c1dd014150964ffec1b556943f572d3e5a8069ce
This commit is contained in:
Olzhas Askar
2026-06-01 08:04:24 +00:00
committed by Copybot
parent f07212337f
commit b5a73efaeb
27 changed files with 162 additions and 99 deletions
@@ -3,16 +3,13 @@ import { useCallback, useEffect, useState } from 'react'
import * as eventTracking from '../../../../infrastructure/event-tracking'
import StartFreeTrialButton from '../../../../shared/components/start-free-trial-button'
import UpgradeBenefits from '@/shared/components/upgrade-benefits'
import { useFeatureFlag } from '@/shared/context/split-test-context'
export function OwnerPaywallPrompt() {
const { t } = useTranslation()
const [clickedFreeTrialButton, setClickedFreeTrialButton] = useState(false)
const plans2026 = useFeatureFlag('plans-2026-phase-1')
useEffect(() => {
eventTracking.send('subscription-funnel', 'editor-click-feature', 'history')
eventTracking.sendMB('paywall-prompt', { 'paywall-type': 'history' })
}, [])
const handleFreeTrialClick = useCallback(() => {
@@ -22,7 +19,7 @@ export function OwnerPaywallPrompt() {
return (
<div className="history-paywall-prompt">
<h2 className="history-paywall-heading">
{plans2026 ? t('get_full_project_history') : t('premium_feature')}
{t('get_full_project_history')}
</h2>
<p>{t('currently_seeing_only_24_hrs_history')}</p>
<p>
@@ -36,7 +33,9 @@ export function OwnerPaywallPrompt() {
source="history"
buttonProps={{ variant: 'premium' }}
handleClick={handleFreeTrialClick}
/>
>
{t('start_free_trial')}
</StartFreeTrialButton>
</p>
{clickedFreeTrialButton ? (
<p className="small">{t('refresh_page_after_starting_free_trial')}</p>
@@ -21,7 +21,7 @@ export const CompileTimeWarningUpgradePromptInner: FC<{
size: 'sm',
}}
>
{t('start_free_trial_without_exclamation')}
{t('start_free_trial')}
</StartFreeTrialButton>
}
ariaLive="polite"
@@ -8,7 +8,7 @@ import getMeta from '@/utils/meta'
import { populateEditorRedesignSegmentation } from '@/shared/hooks/use-editor-analytics'
import CompileTimeoutPaywallModal from '@/features/pdf-preview/components/compile-timeout-paywall-modal'
import { isSplitTestEnabled } from '@/utils/splitTestUtils'
import { useFeatureFlag } from '@/shared/context/split-test-context'
import { useSplitTest } from '@/shared/context/split-test-context'
function TimeoutUpgradePromptNew() {
const { isProjectOwner } = useDetachCompileContext()
@@ -61,7 +61,27 @@ const CompileTimeout = memo(function CompileTimeout({
isCompileTimeoutTargetPlansEnabled,
}: CompileTimeoutProps) {
const { t } = useTranslation()
const plans2026 = useFeatureFlag('plans-2026-phase-1')
const { variant } = useSplitTest('compile-timeout-cta')
let ctaLabel = ''
switch (variant) {
case 'explore-plans':
ctaLabel = t('explore_plans')
break
case 'get-more-compile-time':
ctaLabel = t('get_more_compile_time')
break
case 'upgrade-now':
ctaLabel = t('upgrade_now')
break
case 'subscribe-now':
ctaLabel = t('subscribe_now')
break
default:
ctaLabel = t('start_free_trial')
break
}
const extraSearchParams = useMemo(() => {
return {
itm_content: 'new-editor',
@@ -94,11 +114,7 @@ const CompileTimeout = memo(function CompileTimeout({
{isProjectOwner ? (
<p>
<strong>{t('upgrade_for_more_compile_time')}</strong>{' '}
{plans2026
? t('plus_additional_collaborators_and_more')
: t(
'plus_additional_collaborators_document_history_track_changes_and_more'
)}
{t('plus_additional_collaborators_and_more')}
</p>
) : (
<Trans
@@ -119,7 +135,7 @@ const CompileTimeout = memo(function CompileTimeout({
extraSearchParams={extraSearchParams}
handleClick={handleFreeTrialClick}
>
{t('start_free_trial_without_exclamation')}
{ctaLabel}
</StartFreeTrialButton>
</p>
)}
@@ -18,13 +18,11 @@ import OLRow from '@/shared/components/ol/ol-row'
import OLCol from '@/shared/components/ol/ol-col'
import MaterialIcon from '@/shared/components/material-icon'
import { useEditorContext } from '@/shared/context/editor-context'
import { useFeatureFlag } from '@/shared/context/split-test-context'
function UpgradeTrackChangesModal() {
const { t } = useTranslation()
const { project } = useProjectContext()
const user = useUserContext()
const plans2026 = useFeatureFlag('plans-2026-phase-1')
const {
upgradeTrackChangesModal: { show, location = 'unknown' },
setUpgradeTrackChangesModal,
@@ -74,9 +72,7 @@ function UpgradeTrackChangesModal() {
{[
t('see_suggestions_from_collaborators'),
t('accept_or_reject_individual_edits'),
plans2026
? t('access_all_premium_features_ai')
: t('access_all_premium_features'),
t('access_all_premium_features'),
].map(translation => (
<li key={translation}>
<MaterialIcon type="check" className="check-icon" />
@@ -98,7 +94,7 @@ function UpgradeTrackChangesModal() {
})
}
>
{plans2026 ? t('try_for_free') : t('try_it_for_free')}
{t('try_for_free')}
</OLButton>
) : (
<OLButton
@@ -1,15 +1,13 @@
import { useCallback, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { startFreeTrial } from '@/main/account-upgrade'
import * as eventTracking from '../../infrastructure/event-tracking'
import OLButton from '@/shared/components/ol/ol-button'
import { useFeatureFlag } from '@/shared/context/split-test-context'
type StartFreeTrialButtonProps = {
source: string
children: React.ReactNode
variant?: string
buttonProps?: React.ComponentProps<typeof OLButton>
children?: React.ReactNode
handleClick?: React.ComponentProps<typeof OLButton>['onClick']
segmentation?: eventTracking.Segmentation
extraSearchParams?: Record<string, string>
@@ -26,9 +24,6 @@ export default function StartFreeTrialButton({
segmentation,
extraSearchParams,
}: StartFreeTrialButtonProps) {
const { t } = useTranslation()
const plans2026 = useFeatureFlag('plans-2026-phase-1')
useEffect(() => {
const eventSegmentation: { [key: string]: unknown } = {
'paywall-type': source,
@@ -66,10 +61,7 @@ export default function StartFreeTrialButton({
return (
<OLButton {...buttonProps} onClick={onClick}>
{children ||
(plans2026
? t('start_free_trial_without_exclamation')
: t('start_free_trial'))}
{children}
</OLButton>
)
}