-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Site Migration: Add migration survey (#95408)
* Add generic survey component * Move folder * Implement migration survey * Add survey manager * Update survey layout * Add missing asset * Track events * Limit to display the survey only for english locales
- Loading branch information
1 parent
3f6d739
commit 8095abc
Showing
10 changed files
with
547 additions
and
0 deletions.
There are no files selected for viewing
Binary file added
BIN
+53.7 KB
client/assets/images/onboarding/migrations/survey/wordpress-half-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 43 additions & 0 deletions
43
client/landing/stepper/declarative-flow/internals/components/survery-manager/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { useIsEnglishLocale } from '@automattic/i18n-utils'; | ||
import { | ||
MIGRATION_FLOW, | ||
SITE_MIGRATION_FLOW, | ||
HOSTED_SITE_MIGRATION_FLOW, | ||
MIGRATION_SIGNUP_FLOW, | ||
} from '@automattic/onboarding'; | ||
import { Suspense } from 'react'; | ||
import { useFlowNavigation } from '../../hooks/use-flow-navigation'; | ||
import AsyncMigrationSurvey from '../../steps-repository/components/migration-survey/async'; | ||
|
||
const MIGRATION_SURVEY_FLOWS = [ | ||
MIGRATION_FLOW, | ||
SITE_MIGRATION_FLOW, | ||
HOSTED_SITE_MIGRATION_FLOW, | ||
MIGRATION_SIGNUP_FLOW, | ||
]; | ||
|
||
const SurveyManager = () => { | ||
const { params } = useFlowNavigation(); | ||
const isEnLocale = useIsEnglishLocale(); | ||
|
||
// Skip survey for non-English locales | ||
if ( ! isEnLocale ) { | ||
return null; | ||
} | ||
|
||
if ( ! params.flow ) { | ||
return null; | ||
} | ||
|
||
if ( ! MIGRATION_SURVEY_FLOWS.includes( params.flow ) ) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<Suspense> | ||
<AsyncMigrationSurvey /> | ||
</Suspense> | ||
); | ||
}; | ||
|
||
export default SurveyManager; |
5 changes: 5 additions & 0 deletions
5
...stepper/declarative-flow/internals/steps-repository/components/migration-survey/async.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { lazy } from 'react'; | ||
|
||
const AsyncMigrationSurvey = lazy( () => import( './index' ) ); | ||
|
||
export default AsyncMigrationSurvey; |
50 changes: 50 additions & 0 deletions
50
...stepper/declarative-flow/internals/steps-repository/components/migration-survey/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { Button } from '@wordpress/components'; | ||
import { translate } from 'i18n-calypso'; | ||
import surveyImage from 'calypso/assets/images/onboarding/migrations/survey/wordpress-half-logo.png'; | ||
import { Survey, SurveyProps, SurveyTriggerAccept, SurveyTriggerSkip } from '../survey'; | ||
import './style.scss'; | ||
|
||
type MigrationSurveyProps = Pick< SurveyProps, 'isOpen' >; | ||
|
||
const MigrationSurvey = ( { isOpen }: MigrationSurveyProps ) => { | ||
return ( | ||
<Survey | ||
name="migration-survey" | ||
className="migration-survey" | ||
title={ translate( 'Migration Survey' ) } | ||
isOpen={ isOpen } | ||
> | ||
<div className="migration-survey__popup-img"> | ||
<img src={ surveyImage } alt={ translate( 'Code editor' ) } /> | ||
</div> | ||
<div className="migration-survey__popup-content"> | ||
<h3 className="migration-survey__popup-content-title"> | ||
{ translate( 'Shape the Future of WordPress.com' ) } | ||
</h3> | ||
<div className="migration-survey__popup-content-description"> | ||
{ translate( | ||
'Got a minute? Tell us about your WordPress.com journey in our brief survey and help us serve you better.' | ||
) } | ||
</div> | ||
<div className="migration-survey__popup-content-buttons"> | ||
<SurveyTriggerSkip asChild> | ||
<Button className="migration-survey__popup-content-buttons-cancel"> | ||
{ translate( 'Maybe later' ) } | ||
</Button> | ||
</SurveyTriggerSkip> | ||
<SurveyTriggerAccept asChild> | ||
<Button | ||
variant="primary" | ||
target="_blank" | ||
href="https://automattic.survey.fm/wp-com-migration-survey" | ||
> | ||
{ translate( 'Take survey' ) } | ||
</Button> | ||
</SurveyTriggerAccept> | ||
</div> | ||
</div> | ||
</Survey> | ||
); | ||
}; | ||
|
||
export default MigrationSurvey; |
35 changes: 35 additions & 0 deletions
35
...tepper/declarative-flow/internals/steps-repository/components/migration-survey/style.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
.migration-survey { | ||
.migration-survey__popup-head { | ||
background: #3858e9; | ||
} | ||
|
||
.migration-survey__popup-content { | ||
padding: 18px 24px 30px; | ||
background: var(--studio-white); | ||
|
||
.migration-survey__popup-content-title { | ||
font-weight: 500; | ||
padding-bottom: 8px; | ||
} | ||
|
||
.migration-survey__popup-content-description { | ||
font-size: rem(14px); | ||
line-height: 20px; | ||
padding-bottom: 18px; | ||
} | ||
|
||
.migration-survey__popup-content-buttons { | ||
display: flex; | ||
justify-content: flex-end; | ||
} | ||
.migration-survey__popup-img { | ||
background: #0675c4; | ||
padding-bottom: 57.9%; | ||
|
||
img { | ||
width: 100%; | ||
display: block; | ||
} | ||
} | ||
} | ||
} |
170 changes: 170 additions & 0 deletions
170
...t/landing/stepper/declarative-flow/internals/steps-repository/components/survey/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import { Gridicon } from '@automattic/components'; | ||
import { Button } from '@wordpress/components'; | ||
import clsx from 'clsx'; | ||
import cookie from 'cookie'; | ||
import React, { cloneElement, useCallback, useContext, useMemo, useState } from 'react'; | ||
import { recordTracksEvent } from 'calypso/lib/analytics/tracks'; | ||
import { | ||
type SurveyContextType, | ||
type SurveyActionsContextType, | ||
type TriggerProps, | ||
type SurveyProps, | ||
} from './types'; | ||
export * from './types'; | ||
import './style.scss'; | ||
|
||
const SurveyContext = React.createContext< SurveyContextType | undefined >( undefined ); | ||
|
||
export const SurveyActionsContext = React.createContext< SurveyActionsContextType >( { | ||
accept: () => {}, | ||
skip: () => {}, | ||
} ); | ||
|
||
const Trigger = ( { asChild, children, onClick, as }: TriggerProps ) => { | ||
if ( asChild ) { | ||
return cloneElement( children, { onClick } ); | ||
} | ||
const Tag = as ?? 'button'; | ||
return <Tag onClick={ onClick }>{ children }</Tag>; | ||
}; | ||
|
||
export const SurveyTriggerAccept = ( { | ||
children, | ||
as = 'button', | ||
asChild, | ||
}: Omit< TriggerProps, 'onClick' > ) => { | ||
const { accept } = useContext( SurveyActionsContext ); | ||
return ( | ||
<Trigger as={ as } onClick={ accept } asChild={ asChild }> | ||
{ children } | ||
</Trigger> | ||
); | ||
}; | ||
|
||
export const SurveyTriggerSkip = ( { | ||
children, | ||
as = 'span', | ||
asChild, | ||
}: Omit< TriggerProps, 'onClick' > ) => { | ||
const { skip } = useContext( SurveyActionsContext ); | ||
return ( | ||
<Trigger as={ as } onClick={ skip } asChild={ asChild }> | ||
{ children } | ||
</Trigger> | ||
); | ||
}; | ||
|
||
const bemElement = | ||
( customClassName?: string ) => | ||
( element: string ): string | undefined => { | ||
if ( customClassName ) { | ||
return `${ customClassName }__${ element }`; | ||
} | ||
|
||
return undefined; | ||
}; | ||
|
||
const ONE_YEAR_IN_SECONDS = 1000 * 60 * 60 * 24 * 365; | ||
const ONE_DAY_IN_SECONDS = 1000 * 60 * 60 * 24; | ||
/** | ||
* Generic Survey component | ||
* @example | ||
* ```tsx | ||
* <Survey name="survey-name"> | ||
* <div> | ||
* <h1>Survey</h1> | ||
* <img src="https://wordpress.org/about/assets/images/wp-logo.png" alt="WordPress" /> | ||
* <SurveyTriggerAccept> | ||
* <Button>Take the survey</Button> | ||
* </SurveyTriggerAccept> | ||
* <SurveyTriggerSkip> | ||
* <Button>Skip the survey</Button> | ||
* </SurveyTriggerSkip> | ||
* </div> | ||
* </Survey> | ||
* ``` | ||
*/ | ||
export const Survey = ( { | ||
children, | ||
name, | ||
onAccept, | ||
onSkip, | ||
isOpen = true, | ||
title, | ||
className, | ||
}: SurveyProps ) => { | ||
const cookieValue = cookie.parse( document.cookie ); | ||
const shouldShow = ! cookieValue[ name ]; | ||
const [ shouldShowSurvey, setShouldShowSurvey ] = useState( isOpen && shouldShow ); | ||
const element = bemElement( className ); | ||
|
||
const handleClose = useCallback( | ||
( reason: 'skip' | 'accept' | 'skip_backdrop' ) => { | ||
const PERIOD = reason === 'skip_backdrop' ? ONE_DAY_IN_SECONDS : ONE_YEAR_IN_SECONDS; | ||
|
||
document.cookie = cookie.serialize( name, reason, { | ||
expires: new Date( Date.now() + PERIOD ), | ||
} ); | ||
|
||
if ( reason === 'accept' ) { | ||
recordTracksEvent( 'calypso_survey_accepted', { survey: name, action: reason } ); | ||
onAccept?.(); | ||
} | ||
|
||
if ( reason === 'skip' ) { | ||
recordTracksEvent( 'calypso_survey_skipped', { survey: name, action: reason } ); | ||
onSkip?.(); | ||
} | ||
|
||
setShouldShowSurvey( false ); | ||
}, | ||
[ name, onAccept, onSkip ] | ||
); | ||
|
||
const actions = useMemo( | ||
() => ( { | ||
accept: () => handleClose( 'accept' ), | ||
skip: () => handleClose( 'skip' ), | ||
} ), | ||
[ handleClose ] | ||
); | ||
|
||
if ( ! shouldShowSurvey ) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<SurveyContext.Provider value={ { isOpen } }> | ||
<SurveyActionsContext.Provider value={ actions }> | ||
<div aria-label={ name } className={ clsx( 'survey-notice', className ) }> | ||
<SurveyTriggerSkip asChild> | ||
<button className={ clsx( 'survey-notice__backdrop', element( 'backdrop' ) ) } /> | ||
</SurveyTriggerSkip> | ||
<div className={ clsx( 'survey-notice__popup', element( 'popup' ) ) }> | ||
<div className={ clsx( 'survey-notice__popup-head', element( 'popup-head' ) ) }> | ||
<div | ||
className={ clsx( | ||
'survey-notice__popup-head-title', | ||
element( 'popup-head-title' ) | ||
) } | ||
> | ||
{ title } | ||
</div> | ||
<SurveyTriggerSkip asChild> | ||
<Button | ||
className={ clsx( | ||
'survey-notice__popup-head-close', | ||
element( 'popup-head-close' ) | ||
) } | ||
> | ||
<Gridicon icon="cross" size={ 16 } /> | ||
</Button> | ||
</SurveyTriggerSkip> | ||
</div> | ||
{ children } | ||
</div> | ||
</div> | ||
</SurveyActionsContext.Provider> | ||
</SurveyContext.Provider> | ||
); | ||
}; |
56 changes: 56 additions & 0 deletions
56
.../landing/stepper/declarative-flow/internals/steps-repository/components/survey/style.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
.survey-notice { | ||
position: fixed; | ||
left: 0; | ||
top: 0; | ||
height: 100%; | ||
width: 100%; | ||
z-index: 1000; | ||
|
||
.survey-notice__backdrop { | ||
background: var(--studio-black); | ||
opacity: 0.2; | ||
position: absolute; | ||
left: 0; | ||
top: 0; | ||
width: 100%; | ||
height: 100%; | ||
cursor: default; | ||
} | ||
|
||
.survey-notice__popup { | ||
position: absolute; | ||
right: 25px; | ||
bottom: 25px; | ||
width: 416px; | ||
max-width: calc(100% - 50px); | ||
z-index: 999; | ||
border-radius: 2px; | ||
box-shadow: | ||
0 3px 1px 0 rgba(0, 0, 0, 0.04), | ||
0 3px 8px 0 rgba(0, 0, 0, 0.12); | ||
overflow: hidden; | ||
background-color: var(--studio-white); | ||
} | ||
|
||
.survey-notice__popup-head { | ||
background: #0675c4; | ||
border-bottom: 1px solid #f6f7f7; | ||
height: 56px; | ||
padding: 0 14px 0 16px; | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-between; | ||
|
||
.survey-notice__popup-head-title { | ||
color: var(--studio-white); | ||
font-size: rem(14px); | ||
font-weight: 500; | ||
line-height: 20px; | ||
letter-spacing: -0.15px; | ||
} | ||
|
||
.survey-notice__popup-head-close svg { | ||
fill: var(--studio-white); | ||
} | ||
} | ||
} |
Oops, something went wrong.