From e9547e53d992728b7183e114208106b32acd2916 Mon Sep 17 00:00:00 2001 From: Griffith Chen Date: Tue, 7 Nov 2023 10:14:59 +0800 Subject: [PATCH] Assembler: Implement click to enlarge page preview (#83902) --- .../pattern-assembler/events.ts | 6 +- .../pattern-assembler/index.tsx | 4 +- .../pattern-page-preview-list.tsx | 76 ++++++++++++++----- .../pattern-page-preview.scss | 47 ++++++++++++ .../pattern-page-preview.tsx | 67 +++++++++++++++- 5 files changed, 172 insertions(+), 28 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/events.ts b/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/events.ts index c6ca9bb5f796e..389d172c8b55d 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/events.ts +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/events.ts @@ -47,8 +47,10 @@ export const PATTERN_ASSEMBLER_EVENTS = { /* * Screen Pages */ - SCREEN_PAGES_ADD_PAGE: 'calypso_signup_pattern_assembler_screen_pages_add_page', - SCREEN_PAGES_REMOVE_PAGE: 'calypso_signup_pattern_assembler_screen_pages_remove_page', + SCREEN_PAGES_PAGE_ADD: 'calypso_signup_pattern_assembler_screen_pages_page_add', + SCREEN_PAGES_PAGE_REMOVE: 'calypso_signup_pattern_assembler_screen_pages_page_remove', + SCREEN_PAGES_PAGE_PREVIEW_CLICK: + 'calypso_signup_pattern_assembler_screen_pages_page_preview_click', /** * Pattern Panels diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/index.tsx index 5794ec499915a..630d527207d73 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/index.tsx @@ -518,10 +518,10 @@ const PatternAssembler = ( props: StepProps & NoticesProps ) => { const onScreenPagesSelect = ( page: string ) => { if ( pages.includes( page ) ) { setPages( pages.filter( ( item ) => item !== page ) ); - recordTracksEvent( PATTERN_ASSEMBLER_EVENTS.SCREEN_PAGES_REMOVE_PAGE, { page } ); + recordTracksEvent( PATTERN_ASSEMBLER_EVENTS.SCREEN_PAGES_PAGE_REMOVE, { page } ); } else { setPages( [ ...pages, page ] ); - recordTracksEvent( PATTERN_ASSEMBLER_EVENTS.SCREEN_PAGES_ADD_PAGE, { page } ); + recordTracksEvent( PATTERN_ASSEMBLER_EVENTS.SCREEN_PAGES_PAGE_ADD, { page } ); } }; diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview-list.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview-list.tsx index 5e72028707895..97c0b2679ac2b 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview-list.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview-list.tsx @@ -1,7 +1,13 @@ import { useGlobalStyle } from '@automattic/global-styles'; +import { + __unstableComposite as Composite, + __unstableUseCompositeState as useCompositeState, +} from '@wordpress/components'; import { useTranslate } from 'i18n-calypso'; -import { CSSProperties, useMemo } from 'react'; -import PatternPagePreview from './pattern-page-preview'; +import { CSSProperties, useMemo, useState } from 'react'; +import { recordTracksEvent } from 'calypso/lib/analytics/tracks'; +import { PATTERN_ASSEMBLER_EVENTS } from './events'; +import PatternPagePreview, { PatternPagePreviewModal } from './pattern-page-preview'; import type { Pattern } from './types'; import './pattern-page-preview-list.scss'; @@ -23,6 +29,13 @@ const PatternPagePreviewList = ( { isNewSite, }: Props ) => { const translate = useTranslate(); + const composite = useCompositeState( { orientation: 'horizontal' } ); + const [ zoomedPage, setZoomedPage ] = useState< Pattern[] >( [] ); + + // Using zoomedPage to control whether the modal is opened or not causes a flash of empty content. + // To prevent this, we use another separate state. + // See: https://github.com/Automattic/wp-calypso/pull/83902#discussion_r1383357522. + const [ isModalOpen, setIsModalOpen ] = useState( false ); const [ backgroundColor ] = useGlobalStyle( 'color.background' ); const patternPagePreviewStyle = useMemo( @@ -40,28 +53,51 @@ const PatternPagePreviewList = ( { [ selectedHeader, selectedSections, selectedFooter ] ); + const handleClick = ( patterns: Pattern[], pageSlug: string ) => { + setZoomedPage( patterns ); + setIsModalOpen( true ); + + recordTracksEvent( PATTERN_ASSEMBLER_EVENTS.SCREEN_PAGES_PAGE_PREVIEW_CLICK, { + pattern_names: patterns.map( ( pattern ) => pattern.name ).join( ',' ), + page_slug: pageSlug, + } ); + }; + return ( -
- - { pages.map( ( page ) => ( + <> + handleClick( patterns, 'homepage' ) } /> - ) ) } -
+ { pages.map( ( page, index ) => ( + handleClick( patterns, selectedPages[ index ] ) } + /> + ) ) } + + setIsModalOpen( false ) } + /> + ); }; diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview.scss b/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview.scss index 88c097e46cef2..4752663714043 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview.scss +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview.scss @@ -10,15 +10,27 @@ $font-family: "SF Pro Text", $sans; aspect-ratio: 3/4; .pattern-assembler__preview-frame { + background-color: #f8f8f8; border: 10px solid #f8f8f8; border-radius: 13px; /* stylelint-disable-line scales/radii */ box-shadow: 0 5.25469px 5.25469px 0 rgba(0, 0, 0, 0.02), 0 11.38516px 8.75781px 0 rgba(0, 0, 0, 0.03); + cursor: pointer; flex: 1; min-height: 350px; overflow: hidden; position: relative; + transition: border-color 0.2s; + + &:hover { + background-color: #ebebeb; + border-color: #ebebeb; + } + + &:focus-visible { + outline: 2px solid var(--color-primary-light); + } &-content { background: var(--pattern-page-preview-background, #f8f8f8); @@ -29,6 +41,7 @@ $font-family: "SF Pro Text", $sans; position: absolute; right: 0; top: 0; + user-select: none; /** * Hides the scrollbar to avoid the layout keeps changes forever @@ -51,3 +64,37 @@ $font-family: "SF Pro Text", $sans; margin-top: 16px; } } + +.pattern-assembler__preview-modal { + background-color: #f8f8f8; + border: 18px solid #f8f8f8; + border-radius: 24.894px; /* stylelint-disable-line scales/radii */ + box-shadow: + 0 9.95778px 9.95778px 0 rgba(0, 0, 0, 0.02), + 0 21.57518px 16.59629px 0 rgba(0, 0, 0, 0.03); + + &__backdrop { + background-color: rgba(0, 0, 0, 0.18) !important; + } + + &__wrapper { + border-radius: 16.596px; /* stylelint-disable-line scales/radii */ + padding: 0; + + /** + * Hides the scrollbar to avoid the layout keeps changes forever + * See https://github.com/Automattic/wp-calypso/issues/78357. + */ + scrollbar-width: none; + &::-webkit-scrollbar { + display: none; + } + } + + &__content { + background: var(--pattern-page-preview-background, #f8f8f8); + height: 80vh; + user-select: none; + width: 60vw; + } +} diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview.tsx index 29f02c5f82e5d..edfe4f989ce6d 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/pattern-assembler/pattern-page-preview.tsx @@ -1,25 +1,84 @@ import { PatternRenderer } from '@automattic/block-renderer'; +import { Dialog } from '@automattic/components'; +import { __unstableCompositeItem as CompositeItem } from '@wordpress/components'; import { CSSProperties, useMemo } from 'react'; import { encodePatternId } from './utils'; import type { Pattern } from './types'; import './pattern-page-preview.scss'; -interface Props { +interface PatternPagePreviewModalProps { + style: CSSProperties; + patterns: Pattern[]; + shouldShufflePosts: boolean; + isOpen: boolean; + onClose: () => void; +} + +interface PatternPagePreviewProps { + composite: Record< string, unknown >; title: string; style: CSSProperties; patterns: Pattern[]; shouldShufflePosts: boolean; + onClick: ( patterns: Pattern[] ) => void; } const PATTERN_PAGE_PREVIEW_ITEM_VIEWPORT_HEIGHT = 500; const PATTERN_PAGE_PREVIEW_ITEM_VIEWPORT_WIDTH = 1080; -const PatternPagePreview = ( { title, style, patterns, shouldShufflePosts }: Props ) => { +export const PatternPagePreviewModal = ( { + style, + patterns, + shouldShufflePosts, + isOpen, + onClose, +}: PatternPagePreviewModalProps ) => { + return ( + /* eslint-disable wpcalypso/jsx-classname-namespace */ + +
+ { patterns.map( ( pattern ) => ( + + ) ) } +
+
+ ); +}; + +const PatternPagePreview = ( { + composite, + title, + style, + patterns, + shouldShufflePosts, + onClick, +}: PatternPagePreviewProps ) => { const validPatterns = useMemo( () => patterns.filter( Boolean ) as Pattern[], [ patterns ] ); return (
-
+ onClick( validPatterns ) } + >
{ validPatterns.map( ( pattern ) => ( ) ) }
-
+
{ title }
);