Skip to content

Commit

Permalink
Assembler: Implement click to enlarge page preview (#83902)
Browse files Browse the repository at this point in the history
  • Loading branch information
taipeicoder authored Nov 7, 2023
1 parent fca27da commit e9547e5
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 } );
}
};

Expand Down
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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(
Expand All @@ -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 (
<div className="pattern-assembler__preview-list">
<PatternPagePreview
title={ translate( 'Homepage' ) }
style={ patternPagePreviewStyle }
patterns={ homepage }
shouldShufflePosts={ isNewSite }
/>
{ pages.map( ( page ) => (
<>
<Composite { ...composite } role="listbox" className="pattern-assembler__preview-list">
<PatternPagePreview
key={ page.ID }
composite={ composite }
title={ translate( 'Homepage' ) }
style={ patternPagePreviewStyle }
title={ page.title }
patterns={ [
...( selectedHeader ? [ selectedHeader ] : [] ),
page,
...( selectedFooter ? [ selectedFooter ] : [] ),
] }
shouldShufflePosts={ false }
patterns={ homepage }
shouldShufflePosts={ isNewSite }
onClick={ ( patterns ) => handleClick( patterns, 'homepage' ) }
/>
) ) }
</div>
{ pages.map( ( page, index ) => (
<PatternPagePreview
key={ page.ID }
composite={ composite }
style={ patternPagePreviewStyle }
title={ page.title }
patterns={ [
...( selectedHeader ? [ selectedHeader ] : [] ),
page,
...( selectedFooter ? [ selectedFooter ] : [] ),
] }
shouldShufflePosts={ isNewSite }
onClick={ ( patterns ) => handleClick( patterns, selectedPages[ index ] ) }
/>
) ) }
</Composite>
<PatternPagePreviewModal
style={ patternPagePreviewStyle }
patterns={ zoomedPage }
shouldShufflePosts={ isNewSite }
isOpen={ isModalOpen }
onClose={ () => setIsModalOpen( false ) }
/>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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 */
<Dialog
additionalClassNames="pattern-assembler__preview-modal"
additionalOverlayClassNames="pattern-assembler__preview-modal__backdrop"
className="pattern-assembler__preview-modal__wrapper"
isVisible={ isOpen }
isFullScreen
shouldCloseOnEsc
onClose={ onClose }
>
<div className="pattern-assembler__preview-modal__content" style={ style }>
{ patterns.map( ( pattern ) => (
<PatternRenderer
key={ pattern.ID }
patternId={ encodePatternId( pattern.ID ) }
viewportWidth={ PATTERN_PAGE_PREVIEW_ITEM_VIEWPORT_WIDTH }
viewportHeight={ PATTERN_PAGE_PREVIEW_ITEM_VIEWPORT_HEIGHT }
shouldShufflePosts={ shouldShufflePosts }
/>
) ) }
</div>
</Dialog>
);
};

const PatternPagePreview = ( {
composite,
title,
style,
patterns,
shouldShufflePosts,
onClick,
}: PatternPagePreviewProps ) => {
const validPatterns = useMemo( () => patterns.filter( Boolean ) as Pattern[], [ patterns ] );

return (
<div className="pattern-assembler__preview">
<div className="pattern-assembler__preview-frame">
<CompositeItem
{ ...composite }
role="option"
as="button"
className="pattern-assembler__preview-frame"
aria-label={ title }
onClick={ () => onClick( validPatterns ) }
>
<div className="pattern-assembler__preview-frame-content" style={ style }>
{ validPatterns.map( ( pattern ) => (
<PatternRenderer
Expand All @@ -31,7 +90,7 @@ const PatternPagePreview = ( { title, style, patterns, shouldShufflePosts }: Pro
/>
) ) }
</div>
</div>
</CompositeItem>
<div className="pattern-assembler__preview-title">{ title }</div>
</div>
);
Expand Down

0 comments on commit e9547e5

Please sign in to comment.