From a070808eeea5b70009354c88a3f8722679089b10 Mon Sep 17 00:00:00 2001 From: Volodymyr Makukha Date: Wed, 26 Nov 2025 17:33:38 +0000 Subject: [PATCH 1/8] Add wpcom to onboarding --- src/components/app.tsx | 4 +- src/components/root.tsx | 2 +- src/hooks/use-add-site.ts | 1 + .../add-site/components/blueprints.css | 7 +- .../add-site/components/blueprints.tsx | 4 +- src/modules/add-site/components/stepper.tsx | 6 +- src/modules/add-site/index.tsx | 46 ++++++++---- .../onboarding/components/add-site.tsx | 25 +++++++ .../components/connect-to-wpcom.tsx | 75 +++++++++++++++++++ .../onboarding}/hooks/use-onboarding.tsx | 0 .../onboarding/index.tsx} | 20 +++-- .../user-settings/components/account-tab.tsx | 2 +- src/modules/whats-new/hooks/use-whats-new.tsx | 2 +- 13 files changed, 162 insertions(+), 32 deletions(-) create mode 100644 src/modules/onboarding/components/add-site.tsx create mode 100644 src/modules/onboarding/components/connect-to-wpcom.tsx rename src/{ => modules/onboarding}/hooks/use-onboarding.tsx (100%) rename src/{components/onboarding.tsx => modules/onboarding/index.tsx} (86%) diff --git a/src/components/app.tsx b/src/components/app.tsx index 34c0826cce..fb96c3e1d3 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -5,16 +5,16 @@ import { import { useEffect } from 'react'; import MacTitlebar from 'src/components/mac-titlebar'; import MainSidebar from 'src/components/main-sidebar'; -import Onboarding from 'src/components/onboarding'; import { SiteContentTabs } from 'src/components/site-content-tabs'; import TopBar from 'src/components/top-bar'; import WindowsTitlebar from 'src/components/windows-titlebar'; import { useLocalizationSupport } from 'src/hooks/use-localization-support'; -import { useOnboarding } from 'src/hooks/use-onboarding'; import { useSidebarVisibility } from 'src/hooks/use-sidebar-visibility'; import { isWindows } from 'src/lib/app-globals'; import { cx } from 'src/lib/cx'; import { getIpcApi } from 'src/lib/get-ipc-api'; +import { Onboarding } from 'src/modules/onboarding'; +import { useOnboarding } from 'src/modules/onboarding/hooks/use-onboarding'; import { UserSettings } from 'src/modules/user-settings'; import { WhatsNewModal, useWhatsNew } from 'src/modules/whats-new'; import 'src/index.css'; diff --git a/src/components/root.tsx b/src/components/root.tsx index 3c0a2eb4f4..a8bbddd1fb 100644 --- a/src/components/root.tsx +++ b/src/components/root.tsx @@ -13,9 +13,9 @@ import { SyncSitesProvider } from 'src/hooks/sync-sites/sync-sites-context'; import { ContentTabsProvider } from 'src/hooks/use-content-tabs'; import { FeatureFlagsProvider } from 'src/hooks/use-feature-flags'; import { ImportExportProvider } from 'src/hooks/use-import-export'; -import { OnboardingProvider } from 'src/hooks/use-onboarding'; import { SiteDetailsProvider } from 'src/hooks/use-site-details'; import { ThemeDetailsProvider } from 'src/hooks/use-theme-details'; +import { OnboardingProvider } from 'src/modules/onboarding/hooks/use-onboarding'; import { store } from 'src/stores'; import { initializeUserLocale } from 'src/stores/i18n-slice'; diff --git a/src/hooks/use-add-site.ts b/src/hooks/use-add-site.ts index 50882ce492..829f5eadb4 100644 --- a/src/hooks/use-add-site.ts +++ b/src/hooks/use-add-site.ts @@ -199,6 +199,7 @@ export function useAddSite() { const handleSiteNameChange = useCallback( async ( name: string ) => { setSiteName( name ); + if ( sitePath ) { return; } diff --git a/src/modules/add-site/components/blueprints.css b/src/modules/add-site/components/blueprints.css index 958c9696d3..fb017a9e7d 100644 --- a/src/modules/add-site/components/blueprints.css +++ b/src/modules/add-site/components/blueprints.css @@ -1,6 +1,11 @@ .blueprints-container .dataviews-title-field { @apply px-5 w-full; } + +.blueprints-container .dataviews-view-grid-items { + @apply w-full; +} + .blueprints-container .dataviews-view-grid__card { @apply cursor-pointer relative justify-between outline outline-a8c-gray-5 rounded h-[279px] [@media(min-height:680px)]:h-[340px] min-w-32; } @@ -24,7 +29,7 @@ } .blueprints-container .dataviews-view-grid { - @apply !grid !grid-cols-3 !gap-5 !items-start; + @apply !grid grid-flow-col auto-cols-[minmax(184px,_1fr)] overflow-x-auto overflow-y-hidden !gap-5 p-[1px]; } .blueprints-container .components-badge { diff --git a/src/modules/add-site/components/blueprints.tsx b/src/modules/add-site/components/blueprints.tsx index 906af0c62d..2805b9be5e 100644 --- a/src/modules/add-site/components/blueprints.tsx +++ b/src/modules/add-site/components/blueprints.tsx @@ -403,7 +403,7 @@ export function AddSiteBlueprintSelector( { - + { __( 'Featured Blueprints' ) } @@ -442,7 +442,7 @@ export function AddSiteBlueprintSelector( { ) } -
+
{ isFetchingBlueprints && ( { __( 'Loading Blueprints...' ) } diff --git a/src/modules/add-site/components/stepper.tsx b/src/modules/add-site/components/stepper.tsx index dc838d5f6a..32a2d2c75b 100644 --- a/src/modules/add-site/components/stepper.tsx +++ b/src/modules/add-site/components/stepper.tsx @@ -47,8 +47,8 @@ export default function Stepper( { } return ( -
- +
+ { steps.map( ( step, index ) => { const stepNumber = index + 1; @@ -65,7 +65,7 @@ export default function Stepper( { >
diff --git a/src/modules/add-site/index.tsx b/src/modules/add-site/index.tsx index 22035c08bf..5fbca7d40c 100644 --- a/src/modules/add-site/index.tsx +++ b/src/modules/add-site/index.tsx @@ -27,10 +27,12 @@ import AddSiteOptions, { type AddSiteFlowType } from './components/options'; import { PullRemoteSite } from './components/pull-remote-site'; import Stepper from './components/stepper'; import { useBlueprintDeeplink } from './hooks/use-blueprint-deeplink'; +import { createNodeFsMountHandler } from '@php-wasm/node'; interface AddSiteProps { className?: string; variant?: ButtonVariant; + withCtaButton?: boolean; } type BlueprintsData = ReturnType< typeof useGetBlueprints >[ 'data' ]; @@ -279,7 +281,11 @@ function NavigationContent( props: NavigationContentProps ) { ); } -export default function AddSite( { className, variant = 'outlined' }: AddSiteProps ) { +export default function AddSite( { + className, + variant = 'outlined', + withCtaButton = true, +}: AddSiteProps ) { const { __ } = useI18n(); const [ showModal, setShowModal ] = useState( false ); const [ nameSuggested, setNameSuggested ] = useState( false ); @@ -419,10 +425,10 @@ export default function AddSite( { className, variant = 'outlined' }: AddSitePro ] ); useEffect( () => { - if ( showModal && ! nameSuggested && ! loadingSites ) { + if ( ( showModal || ! withCtaButton ) && ! nameSuggested && ! loadingSites ) { void initializeForm(); } - }, [ showModal, nameSuggested, loadingSites, initializeForm ] ); + }, [ showModal, withCtaButton, nameSuggested, loadingSites, initializeForm ] ); const handleSubmit = useCallback( async ( event: FormEvent ) => { @@ -442,22 +448,30 @@ export default function AddSite( { className, variant = 'outlined' }: AddSitePro openModal(); } ); + const WrapperContent = ( + + + + ); + + if ( ! withCtaButton ) { + return WrapperContent; + } + return ( <> - - - + { WrapperContent } +
+ ) } +
+ ); +} diff --git a/src/modules/onboarding/components/connect-to-wpcom.tsx b/src/modules/onboarding/components/connect-to-wpcom.tsx new file mode 100644 index 0000000000..9957155346 --- /dev/null +++ b/src/modules/onboarding/components/connect-to-wpcom.tsx @@ -0,0 +1,75 @@ +import { __experimentalHeading as Heading } from '@wordpress/components'; +import { useI18n } from '@wordpress/react-i18n'; +import { ArrowIcon } from 'src/components/arrow-icon'; +import Button from 'src/components/button'; +import offlineIcon from 'src/components/offline-icon'; +import { Tooltip } from 'src/components/tooltip'; +import { useAuth } from 'src/hooks/use-auth'; +import { useOffline } from 'src/hooks/use-offline'; +import { getIpcApi } from 'src/lib/get-ipc-api'; + +export function OnboardingConnectToWpcom( { onSkip }: { onSkip: () => void } ) { + const { __ } = useI18n(); + const isOffline = useOffline(); + const offlineMessage = __( "You're currently offline." ); + const { authenticate } = useAuth(); + + return ( +
+
+ + { __( 'Connect to your WordPress.com account' ) } + + + + + + + + + { __( 'New to WordPress.com?' ) }{ ' ' } + + + +
+ +
+ +
+
+ ); +} diff --git a/src/hooks/use-onboarding.tsx b/src/modules/onboarding/hooks/use-onboarding.tsx similarity index 100% rename from src/hooks/use-onboarding.tsx rename to src/modules/onboarding/hooks/use-onboarding.tsx diff --git a/src/components/onboarding.tsx b/src/modules/onboarding/index.tsx similarity index 86% rename from src/components/onboarding.tsx rename to src/modules/onboarding/index.tsx index 57e498d219..5debe6c308 100644 --- a/src/components/onboarding.tsx +++ b/src/modules/onboarding/index.tsx @@ -1,13 +1,16 @@ import { speak } from '@wordpress/a11y'; import { sprintf } from '@wordpress/i18n'; import { useI18n } from '@wordpress/react-i18n'; -import { FormEvent, useCallback, useEffect } from 'react'; +import { FormEvent, useCallback, useEffect, useState } from 'react'; import Button from 'src/components/button'; import { SiteForm } from 'src/components/site-form'; import { StudioLogo } from 'src/components/studio-logo'; import { useAddSite } from 'src/hooks/use-add-site'; +import { useAuth } from 'src/hooks/use-auth'; import { generateSiteName } from 'src/lib/generate-site-name'; import { getIpcApi } from 'src/lib/get-ipc-api'; +import { OnboardingAddSite } from 'src/modules/onboarding/components/add-site'; +import { OnboardingConnectToWpcom } from 'src/modules/onboarding/components/connect-to-wpcom'; import { useAppDispatch, useRootSelector } from 'src/stores'; import { useSaveLastSeenVersionMutation } from 'src/stores/app-version-api'; import { saveOnboardingStatus } from 'src/stores/onboarding-slice'; @@ -35,9 +38,11 @@ const GradientBox = () => { ); }; -export default function Onboarding() { +export function Onboarding() { const { __ } = useI18n(); const dispatch = useAppDispatch(); + const [ isWpAccSkipped, setIsWpAccSkipped ] = useState( false ); + const { isAuthenticated } = useAuth(); const [ saveLastSeenVersion ] = useSaveLastSeenVersionMutation(); const { setSiteName, @@ -131,9 +136,14 @@ export default function Onboarding() {
-
+
-
+ { ! isWpAccSkipped && ! isAuthenticated ? ( + setIsWpAccSkipped( true ) } /> + ) : ( + setIsWpAccSkipped( false ) } /> + ) } + {/*

{ __( 'Add your first site' ) }

@@ -167,7 +177,7 @@ export default function Onboarding() {

-
+
*/}
diff --git a/src/modules/user-settings/components/account-tab.tsx b/src/modules/user-settings/components/account-tab.tsx index 5b8652632c..8800fac9ae 100644 --- a/src/modules/user-settings/components/account-tab.tsx +++ b/src/modules/user-settings/components/account-tab.tsx @@ -5,7 +5,7 @@ import { Tooltip } from 'src/components/tooltip'; import { WPCOM_PROFILE_URL } from 'src/constants'; import { getIpcApi } from 'src/lib/get-ipc-api'; -export const UserInfo = ( { +const UserInfo = ( { user, onLogout, }: { diff --git a/src/modules/whats-new/hooks/use-whats-new.tsx b/src/modules/whats-new/hooks/use-whats-new.tsx index 3309ee9906..b3cd4cd1b5 100644 --- a/src/modules/whats-new/hooks/use-whats-new.tsx +++ b/src/modules/whats-new/hooks/use-whats-new.tsx @@ -1,6 +1,6 @@ import { useState } from 'react'; import { useIpcListener } from 'src/hooks/use-ipc-listener'; -import { useOnboarding } from 'src/hooks/use-onboarding'; +import { useOnboarding } from 'src/modules/onboarding/hooks/use-onboarding'; import { useLastSeenVersion } from 'src/modules/whats-new/hooks/use-last-seen-version'; interface UseWhatsNew { From 381d55ad7ee305f16022f4db4cb60d712c235662 Mon Sep 17 00:00:00 2001 From: Volodymyr Makukha Date: Thu, 27 Nov 2025 14:52:57 +0000 Subject: [PATCH 2/8] Revert and add new flow --- src/hooks/use-add-site.ts | 1 - .../add-site/components/blueprints.css | 6 +-- .../add-site/components/blueprints.tsx | 4 +- src/modules/add-site/index.tsx | 46 +++++++------------ .../onboarding/components/add-site.tsx | 25 ---------- src/modules/onboarding/index.tsx | 15 +++--- 6 files changed, 27 insertions(+), 70 deletions(-) delete mode 100644 src/modules/onboarding/components/add-site.tsx diff --git a/src/hooks/use-add-site.ts b/src/hooks/use-add-site.ts index 829f5eadb4..50882ce492 100644 --- a/src/hooks/use-add-site.ts +++ b/src/hooks/use-add-site.ts @@ -199,7 +199,6 @@ export function useAddSite() { const handleSiteNameChange = useCallback( async ( name: string ) => { setSiteName( name ); - if ( sitePath ) { return; } diff --git a/src/modules/add-site/components/blueprints.css b/src/modules/add-site/components/blueprints.css index fb017a9e7d..f3916ebb68 100644 --- a/src/modules/add-site/components/blueprints.css +++ b/src/modules/add-site/components/blueprints.css @@ -2,10 +2,6 @@ @apply px-5 w-full; } -.blueprints-container .dataviews-view-grid-items { - @apply w-full; -} - .blueprints-container .dataviews-view-grid__card { @apply cursor-pointer relative justify-between outline outline-a8c-gray-5 rounded h-[279px] [@media(min-height:680px)]:h-[340px] min-w-32; } @@ -29,7 +25,7 @@ } .blueprints-container .dataviews-view-grid { - @apply !grid grid-flow-col auto-cols-[minmax(184px,_1fr)] overflow-x-auto overflow-y-hidden !gap-5 p-[1px]; + @apply !grid !grid-cols-3 !gap-5 !items-start; } .blueprints-container .components-badge { diff --git a/src/modules/add-site/components/blueprints.tsx b/src/modules/add-site/components/blueprints.tsx index 2805b9be5e..906af0c62d 100644 --- a/src/modules/add-site/components/blueprints.tsx +++ b/src/modules/add-site/components/blueprints.tsx @@ -403,7 +403,7 @@ export function AddSiteBlueprintSelector( { - + { __( 'Featured Blueprints' ) } @@ -442,7 +442,7 @@ export function AddSiteBlueprintSelector( { ) } -
+
{ isFetchingBlueprints && ( { __( 'Loading Blueprints...' ) } diff --git a/src/modules/add-site/index.tsx b/src/modules/add-site/index.tsx index 5fbca7d40c..22035c08bf 100644 --- a/src/modules/add-site/index.tsx +++ b/src/modules/add-site/index.tsx @@ -27,12 +27,10 @@ import AddSiteOptions, { type AddSiteFlowType } from './components/options'; import { PullRemoteSite } from './components/pull-remote-site'; import Stepper from './components/stepper'; import { useBlueprintDeeplink } from './hooks/use-blueprint-deeplink'; -import { createNodeFsMountHandler } from '@php-wasm/node'; interface AddSiteProps { className?: string; variant?: ButtonVariant; - withCtaButton?: boolean; } type BlueprintsData = ReturnType< typeof useGetBlueprints >[ 'data' ]; @@ -281,11 +279,7 @@ function NavigationContent( props: NavigationContentProps ) { ); } -export default function AddSite( { - className, - variant = 'outlined', - withCtaButton = true, -}: AddSiteProps ) { +export default function AddSite( { className, variant = 'outlined' }: AddSiteProps ) { const { __ } = useI18n(); const [ showModal, setShowModal ] = useState( false ); const [ nameSuggested, setNameSuggested ] = useState( false ); @@ -425,10 +419,10 @@ export default function AddSite( { ] ); useEffect( () => { - if ( ( showModal || ! withCtaButton ) && ! nameSuggested && ! loadingSites ) { + if ( showModal && ! nameSuggested && ! loadingSites ) { void initializeForm(); } - }, [ showModal, withCtaButton, nameSuggested, loadingSites, initializeForm ] ); + }, [ showModal, nameSuggested, loadingSites, initializeForm ] ); const handleSubmit = useCallback( async ( event: FormEvent ) => { @@ -448,30 +442,22 @@ export default function AddSite( { openModal(); } ); - const WrapperContent = ( - - - - ); - - if ( ! withCtaButton ) { - return WrapperContent; - } - return ( <> - { WrapperContent } + + + -
- ) } -
- ); -} diff --git a/src/modules/onboarding/index.tsx b/src/modules/onboarding/index.tsx index 5debe6c308..fb3dd3aff2 100644 --- a/src/modules/onboarding/index.tsx +++ b/src/modules/onboarding/index.tsx @@ -9,7 +9,6 @@ import { useAddSite } from 'src/hooks/use-add-site'; import { useAuth } from 'src/hooks/use-auth'; import { generateSiteName } from 'src/lib/generate-site-name'; import { getIpcApi } from 'src/lib/get-ipc-api'; -import { OnboardingAddSite } from 'src/modules/onboarding/components/add-site'; import { OnboardingConnectToWpcom } from 'src/modules/onboarding/components/connect-to-wpcom'; import { useAppDispatch, useRootSelector } from 'src/stores'; import { useSaveLastSeenVersionMutation } from 'src/stores/app-version-api'; @@ -41,7 +40,6 @@ const GradientBox = () => { export function Onboarding() { const { __ } = useI18n(); const dispatch = useAppDispatch(); - const [ isWpAccSkipped, setIsWpAccSkipped ] = useState( false ); const { isAuthenticated } = useAuth(); const [ saveLastSeenVersion ] = useSaveLastSeenVersionMutation(); const { @@ -127,6 +125,13 @@ export function Onboarding() { [ handleAddSiteClick, siteAddedMessage, dispatch, saveLastSeenVersion ] ); + const handleSkip = useCallback( async () => { + // Save current app version to prevent What's New from showing for new users + await saveLastSeenVersion( window.appGlobals.appVersion ); + + await dispatch( saveOnboardingStatus( true ) ); + }, [ dispatch, saveLastSeenVersion ] ); + return (
@@ -138,11 +143,7 @@ export function Onboarding() {
- { ! isWpAccSkipped && ! isAuthenticated ? ( - setIsWpAccSkipped( true ) } /> - ) : ( - setIsWpAccSkipped( false ) } /> - ) } + {/*

{ __( 'Add your first site' ) }

From 1e300c11c307790536cf54d52575539a5b7b6011 Mon Sep 17 00:00:00 2001 From: Volodymyr Makukha Date: Thu, 27 Nov 2025 14:54:10 +0000 Subject: [PATCH 3/8] space --- src/modules/add-site/components/blueprints.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/add-site/components/blueprints.css b/src/modules/add-site/components/blueprints.css index f3916ebb68..958c9696d3 100644 --- a/src/modules/add-site/components/blueprints.css +++ b/src/modules/add-site/components/blueprints.css @@ -1,7 +1,6 @@ .blueprints-container .dataviews-title-field { @apply px-5 w-full; } - .blueprints-container .dataviews-view-grid__card { @apply cursor-pointer relative justify-between outline outline-a8c-gray-5 rounded h-[279px] [@media(min-height:680px)]:h-[340px] min-w-32; } From e670492b9d7579c9b3affbe85a5f9194b929e15b Mon Sep 17 00:00:00 2001 From: Volodymyr Makukha Date: Thu, 27 Nov 2025 14:55:49 +0000 Subject: [PATCH 4/8] adjust --- src/modules/add-site/components/stepper.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/add-site/components/stepper.tsx b/src/modules/add-site/components/stepper.tsx index 32a2d2c75b..dc838d5f6a 100644 --- a/src/modules/add-site/components/stepper.tsx +++ b/src/modules/add-site/components/stepper.tsx @@ -47,8 +47,8 @@ export default function Stepper( { } return ( -
- +
+ { steps.map( ( step, index ) => { const stepNumber = index + 1; @@ -65,7 +65,7 @@ export default function Stepper( { >
From a092c4ab65b0d7c7d8bd1b9c93da2382f6d98081 Mon Sep 17 00:00:00 2001 From: Volodymyr Makukha Date: Thu, 27 Nov 2025 15:08:36 +0000 Subject: [PATCH 5/8] Final preparation --- src/modules/onboarding/index.tsx | 138 ++----------------------------- 1 file changed, 9 insertions(+), 129 deletions(-) diff --git a/src/modules/onboarding/index.tsx b/src/modules/onboarding/index.tsx index fb3dd3aff2..be4446c11c 100644 --- a/src/modules/onboarding/index.tsx +++ b/src/modules/onboarding/index.tsx @@ -1,20 +1,11 @@ -import { speak } from '@wordpress/a11y'; -import { sprintf } from '@wordpress/i18n'; import { useI18n } from '@wordpress/react-i18n'; -import { FormEvent, useCallback, useEffect, useState } from 'react'; -import Button from 'src/components/button'; -import { SiteForm } from 'src/components/site-form'; +import { useCallback, useEffect } from 'react'; import { StudioLogo } from 'src/components/studio-logo'; -import { useAddSite } from 'src/hooks/use-add-site'; import { useAuth } from 'src/hooks/use-auth'; -import { generateSiteName } from 'src/lib/generate-site-name'; -import { getIpcApi } from 'src/lib/get-ipc-api'; import { OnboardingConnectToWpcom } from 'src/modules/onboarding/components/connect-to-wpcom'; -import { useAppDispatch, useRootSelector } from 'src/stores'; +import { useAppDispatch } from 'src/stores'; import { useSaveLastSeenVersionMutation } from 'src/stores/app-version-api'; import { saveOnboardingStatus } from 'src/stores/onboarding-slice'; -import { selectMinimumWordPressVersion } from 'src/stores/provider-constants-slice'; -import { useGetWordPressVersions } from 'src/stores/wordpress-versions-api'; const GradientBox = () => { const { __ } = useI18n(); @@ -42,88 +33,6 @@ export function Onboarding() { const dispatch = useAppDispatch(); const { isAuthenticated } = useAuth(); const [ saveLastSeenVersion ] = useSaveLastSeenVersionMutation(); - const { - setSiteName, - setProposedSitePath, - setSitePath, - setError, - setDoesPathContainWordPress, - setPhpVersion, - setWpVersion, - siteName, - sitePath, - error, - doesPathContainWordPress, - handleAddSiteClick, - handleSiteNameChange, - handlePathSelectorClick, - phpVersion, - wpVersion, - useCustomDomain, - setUseCustomDomain, - customDomain, - setCustomDomain, - customDomainError, - setCustomDomainError, - enableHttps, - setEnableHttps, - loadAllCustomDomains, - } = useAddSite(); - - const siteAddedMessage = sprintf( - // translators: %s is the site name. - __( '%s site added.' ), - siteName || '' - ); - - const minimumWordPressVersion = useRootSelector( selectMinimumWordPressVersion ); - const { data: versions = [] } = useGetWordPressVersions( { - minimumVersion: minimumWordPressVersion, - } ); - const latestStableVersion = versions.find( ( version ) => version.value === 'latest' ); - - useEffect( () => { - if ( latestStableVersion ) { - setWpVersion( latestStableVersion.value ); - } - }, [ latestStableVersion, setWpVersion ] ); - - useEffect( () => { - const run = async () => { - const siteName = await generateSiteName( [] ); - const { path, name, isWordPress } = await getIpcApi().generateProposedSitePath( siteName ); - setSiteName( name ); - setProposedSitePath( path ); - setSitePath( '' ); - setError( '' ); - setDoesPathContainWordPress( isWordPress ); - setUseCustomDomain( false ); - setCustomDomain( null ); - setCustomDomainError( '' ); - setEnableHttps( false ); - loadAllCustomDomains(); - }; - void run(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [] ); - - const handleSubmit = useCallback( - async ( event: FormEvent ) => { - event.preventDefault(); - // Save current app version to prevent What's New from showing for new users - await saveLastSeenVersion( window.appGlobals.appVersion ); - - try { - await handleAddSiteClick(); - // Save onboarding completion after site is successfully created - await dispatch( saveOnboardingStatus( true ) ); - speak( siteAddedMessage ); - } catch { - // No need to handle error here, it's already handled in handleAddSiteClick - } - }, - [ handleAddSiteClick, siteAddedMessage, dispatch, saveLastSeenVersion ] - ); const handleSkip = useCallback( async () => { // Save current app version to prevent What's New from showing for new users @@ -132,6 +41,12 @@ export function Onboarding() { await dispatch( saveOnboardingStatus( true ) ); }, [ dispatch, saveLastSeenVersion ] ); + useEffect( () => { + if ( isAuthenticated ) { + void handleSkip(); + } + }, [ isAuthenticated, handleSkip ] ); + return (
@@ -141,44 +56,9 @@ export function Onboarding() {
-
+
- {/*
-
-

{ __( 'Add your first site' ) }

-

- { __( "Add your first site and explore Studio's powerful workflow and features." ) } -

-
- -
- -
-
-
*/}
From a72736c52ad93e153d10c5f7547f2e2218be9d3a Mon Sep 17 00:00:00 2001 From: Volodymyr Makukha Date: Thu, 27 Nov 2025 15:53:35 +0000 Subject: [PATCH 6/8] Fix lint --- src/components/tests/onboarding.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/tests/onboarding.test.tsx b/src/components/tests/onboarding.test.tsx index db80e76fa5..cdf3062765 100644 --- a/src/components/tests/onboarding.test.tsx +++ b/src/components/tests/onboarding.test.tsx @@ -3,13 +3,13 @@ import { jest } from '@jest/globals'; import { render, waitFor, screen } from '@testing-library/react'; import { userEvent } from '@testing-library/user-event'; import { Provider } from 'react-redux'; -import Onboarding from 'src/components/onboarding'; import { useAddSite } from 'src/hooks/use-add-site'; import { useOffline } from 'src/hooks/use-offline'; -import { useOnboarding } from 'src/hooks/use-onboarding'; import { FolderDialogResponse } from 'src/ipc-handlers'; import { createTestStore } from 'src/lib/test-utils'; import { getWordPressProvider } from 'src/lib/wordpress-provider'; +import { Onboarding } from 'src/modules/onboarding'; +import { useOnboarding } from 'src/modules/onboarding/hooks/use-onboarding'; import { useGetWordPressVersions } from 'src/stores/wordpress-versions-api'; jest.mock( 'src/hooks/use-onboarding', () => ( { From ff991a025fcb3c1f515de36ffbafd1fce078f10c Mon Sep 17 00:00:00 2001 From: Volodymyr Makukha Date: Thu, 27 Nov 2025 16:33:44 +0000 Subject: [PATCH 7/8] Clean up siteForm from legacy --- .../{site-form.tsx => create-site-form.tsx} | 166 +----------------- .../add-site/components/create-site.tsx | 4 +- 2 files changed, 7 insertions(+), 163 deletions(-) rename src/components/{site-form.tsx => create-site-form.tsx} (74%) diff --git a/src/components/site-form.tsx b/src/components/create-site-form.tsx similarity index 74% rename from src/components/site-form.tsx rename to src/components/create-site-form.tsx index e9212de486..0e8d579359 100644 --- a/src/components/site-form.tsx +++ b/src/components/create-site-form.tsx @@ -1,21 +1,13 @@ import { Icon, SelectControl, Notice } from '@wordpress/components'; import { createInterpolateElement } from '@wordpress/element'; import { __, sprintf, _n } from '@wordpress/i18n'; -import { - tip, - cautionFilled, - trash, - chevronRight, - chevronDown, - chevronLeft, -} from '@wordpress/icons'; +import { tip, cautionFilled, chevronRight, chevronDown, chevronLeft } from '@wordpress/icons'; import { useI18n } from '@wordpress/react-i18n'; -import { FormEvent, useRef, useState, useEffect } from 'react'; +import { FormEvent, useState, useEffect } from 'react'; import Button from 'src/components/button'; import FolderIcon from 'src/components/folder-icon'; import TextControlComponent from 'src/components/text-control'; import { WPVersionSelector } from 'src/components/wp-version-selector'; -import { ACCEPTED_IMPORT_FILE_TYPES } from 'src/constants'; import { cx } from 'src/lib/cx'; import { generateCustomDomainFromSiteName } from 'src/lib/domains'; import { getIpcApi } from 'src/lib/get-ipc-api'; @@ -33,19 +25,9 @@ interface FormPathInputComponentProps { onClick: () => void; error?: string; doesPathContainWordPress: boolean; - isDisabled: boolean; id?: string; } -interface FormImportComponentProps { - value?: File | null; - onFileSelected?: ( file: File ) => void; - onClear?: () => void; - onChange: ( file: File | null ) => void; - error?: string; - placeholder?: string; -} - interface SiteFormErrorProps { error?: string; tipMessage?: string; @@ -53,20 +35,13 @@ interface SiteFormErrorProps { } interface SiteFormProps { - className?: string; - children?: React.ReactNode; siteName: string; setSiteName: ( name: string ) => void; sitePath?: string; onSelectPath?: () => void; error: string; doesPathContainWordPress?: boolean; - isPathInputDisabled?: boolean; onSubmit: ( event: FormEvent ) => void; - fileForImport?: File | null; - setFileForImport?: ( file: File | null ) => void; - onFileSelected?: ( file: File ) => void; - fileError?: string; useCustomDomain?: boolean; setUseCustomDomain?: ( use: boolean ) => void; customDomain?: string | null; @@ -112,7 +87,6 @@ function FormPathInputComponent( { onClick, error, doesPathContainWordPress, - isDisabled = false, id, }: FormPathInputComponentProps ) { const { __ } = useI18n(); @@ -136,7 +110,6 @@ function FormPathInputComponent( { error && 'border-red-500 [&_.local-path-icon]:border-l-red-500' ) } data-testid="select-path-button" - disabled={ isDisabled } onClick={ onClick } id={ id } > @@ -165,91 +138,7 @@ function FormPathInputComponent( { ); } -function FormImportComponent( { - value, - onFileSelected, - onClear, - error, - placeholder, -}: FormImportComponentProps ) { - const fileName = value ? value.name : ''; - - const inputFileRef = useRef< HTMLInputElement >( null ); - - const handleIconClick = ( event: FormEvent ) => { - event.stopPropagation(); - if ( onClear ) { - onClear(); - if ( inputFileRef.current ) { - inputFileRef.current.value = ''; - } - } - }; - - const handleFileChange = ( event: React.ChangeEvent< HTMLInputElement > ) => { - if ( ! onFileSelected ) { - return; - } - if ( event.target.files && event.target.files[ 0 ] ) { - onFileSelected( event.target.files[ 0 ] ); - } - }; - - return ( - <> -
- - { fileName && ( - - ) } - -
- - - ); -} -export const SiteForm = ( { - className, - children, +export const CreateSiteForm = ( { siteName, setSiteName, phpVersion, @@ -259,13 +148,8 @@ export const SiteForm = ( { sitePath = '', onSelectPath, error, - doesPathContainWordPress = false, - isPathInputDisabled = false, onSubmit, - fileForImport, - setFileForImport, - onFileSelected, - fileError, + doesPathContainWordPress = false, useCustomDomain, setUseCustomDomain, customDomain = null, @@ -315,7 +199,7 @@ export const SiteForm = ( { ( blueprintPreferredVersions.wp && blueprintPreferredVersions.wp !== wpVersion ) ); return ( -
+
- - { setFileForImport && ( - <> -
- - - { createInterpolateElement( - __( - 'Import a Jetpack backup or a full-site backup in another format. ' - ), - { - button: ( -
- - ) } - { onSelectPath && ( <>
@@ -422,7 +268,6 @@ export const SiteForm = ( { ) } ) }
- { children } ); }; diff --git a/src/modules/add-site/components/create-site.tsx b/src/modules/add-site/components/create-site.tsx index 9dc0f64b16..08aec10ccd 100644 --- a/src/modules/add-site/components/create-site.tsx +++ b/src/modules/add-site/components/create-site.tsx @@ -4,7 +4,7 @@ import { } from '@wordpress/components'; import { useI18n } from '@wordpress/react-i18n'; import { FormEvent } from 'react'; -import { SiteForm } from 'src/components/site-form'; +import { CreateSiteForm } from 'src/components/create-site-form'; interface CreateSiteProps { siteName: string | null; @@ -57,7 +57,7 @@ export default function CreateSite( { { __( 'Add a site' ) } - void handleSiteNameChange( name ) } phpVersion={ phpVersion } From 4a67421ee3b6d516ab51d7b10b371b7058b7d9db Mon Sep 17 00:00:00 2001 From: Volodymyr Makukha Date: Thu, 27 Nov 2025 16:42:31 +0000 Subject: [PATCH 8/8] Move component to modules --- src/{ => modules/add-site}/components/create-site-form.tsx | 0 src/modules/add-site/components/create-site.tsx | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{ => modules/add-site}/components/create-site-form.tsx (100%) diff --git a/src/components/create-site-form.tsx b/src/modules/add-site/components/create-site-form.tsx similarity index 100% rename from src/components/create-site-form.tsx rename to src/modules/add-site/components/create-site-form.tsx diff --git a/src/modules/add-site/components/create-site.tsx b/src/modules/add-site/components/create-site.tsx index 08aec10ccd..0f57a01b61 100644 --- a/src/modules/add-site/components/create-site.tsx +++ b/src/modules/add-site/components/create-site.tsx @@ -4,7 +4,7 @@ import { } from '@wordpress/components'; import { useI18n } from '@wordpress/react-i18n'; import { FormEvent } from 'react'; -import { CreateSiteForm } from 'src/components/create-site-form'; +import { CreateSiteForm } from 'src/modules/add-site/components/create-site-form'; interface CreateSiteProps { siteName: string | null;