Skip to content

Commit

Permalink
My Jetpack: Adding new modal interstitial (#40945)
Browse files Browse the repository at this point in the history
* My Jetpack: Adding new modal interstitial component

* changelog
  • Loading branch information
grzegorz-cp authored Jan 20, 2025
1 parent 0ed6e32 commit 1b367b3
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { Text, Button, ThemeProvider, Col, Container } from '@automattic/jetpack-components';
import { Modal } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import clsx from 'clsx';
import { useCallback, useState, type FC } from 'react';
import styles from './style.module.scss';

interface ProductInterstitialModalProps {
title: string;
hideCloseButton?: boolean;
triggerButton?: React.ReactNode;
className?: string;
children?: React.ReactNode;
secondaryColumn?: React.ReactNode;
additionalColumn?: React.ReactNode;
onOpen?: () => void;
onClose?: () => void;
onClick?: () => void;
secondaryButtonExternalLink?: boolean;
secondaryButtonHref?: string;
buttonDisabled?: boolean;
buttonExternalLink?: boolean;
buttonHref?: string;
buttonContent?: string;
}

const ProductInterstitialModal: FC< ProductInterstitialModalProps > = props => {
const {
title,
className,
children,
triggerButton,
onOpen,
onClose,
onClick,
buttonDisabled,
buttonExternalLink,
buttonHref,
buttonContent,
secondaryButtonExternalLink,
secondaryButtonHref,
secondaryColumn,
additionalColumn = false,
} = props;

const [ isOpen, setOpen ] = useState( false );
const openModal = useCallback( () => {
onOpen?.();
setOpen( true );
}, [ onOpen ] );
const closeModal = useCallback( () => {
onClose?.();
setOpen( false );
}, [ onClose ] );

if ( ! title || ! children || ! triggerButton ) {
return null;
}

return (
<>
<ThemeProvider>
{
// TODO: use any component as a trigger
}
<Button variant="secondary" onClick={ openModal }>
{ triggerButton }
</Button>
{ isOpen && (
<Modal
onRequestClose={ closeModal }
className={ clsx( styles[ 'component-product-interstitial-modal' ], className ) }
>
<Container
className={ styles.wrapper }
horizontalSpacing={ 0 }
horizontalGap={ 1 }
fluid={ false }
>
{
// left column - always takes 33% of the width or the full with for small breakpoint
}
<Col sm={ 4 } md={ 8 } lg={ 4 } className={ styles.primary }>
<div className={ styles[ 'primary-content' ] }>
<div className={ styles.header }>
<Text variant="headline-small" className={ styles.title }>
{ title }
</Text>
</div>
{ children }
</div>
<div className={ styles[ 'primary-footer' ] }>
<Button
variant="primary"
className={ styles[ 'action-button' ] }
disabled={ buttonDisabled }
onClick={ onClick }
isExternalLink={ buttonExternalLink }
href={ buttonHref }
>
{ buttonContent }
</Button>
<Button
variant="link"
isExternalLink={ secondaryButtonExternalLink }
href={ secondaryButtonHref }
>
{ __( 'Learn more', 'jetpack-my-jetpack' ) }
</Button>
</div>
</Col>
{
// middle column for three columns layout and the right column for two columns layout
// small breakpoint: takes full width
// medium breakpoint: ~63% of the width without the additional column or 50% of the second row with the additional column
// large breakpoint: 66% of the width without the additional column or 33% with the additional column
}
<Col
sm={ 4 }
md={ additionalColumn ? 4 : 5 }
lg={ additionalColumn ? 4 : 8 }
className={ styles.secondary }
>
{ secondaryColumn }
</Col>
{
// additional column for three columns layout
// small breakpoint (max 4 cols): takes full width
// medium breakpoint (max 8 cols): 50% of the second row width
// large breakpoint (max 12 cols): 33% of the width
additionalColumn && (
<Col sm={ 4 } md={ 4 } lg={ 4 } className={ styles.additional }>
{ additionalColumn }
</Col>
)
}
</Container>
</Modal>
) }
</ThemeProvider>
</>
);
};

export default ProductInterstitialModal;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Text, ProductPrice } from '@automattic/jetpack-components';
import React from 'react';
import { HashRouter, Routes, Route } from 'react-router-dom';
import ProductInterstitialModal from '..';
import boostImage from './boost.png';

export default {
title: 'Packages/My Jetpack/Product Interstitial Modal',
component: ProductInterstitialModal,
};

const DefaultArgs = {
title: 'Product Interstitial Modal',
children: (
<div style={ { display: 'flex', flexDirection: 'column', gap: '1rem' } }>
<Text>
Lorem ipsum dolor <b>sit amet</b>, consectetur adipiscing elit. Cras rutrum neque odio, vel
viverra lectus vulputate et. Lorem ipsum dolor <b>sit amet</b>, consectetur adipiscing elit.
Cras rutrum neque odio, vel viverra lectus vulputate et. Lorem ipsum dolor <b>sit amet</b>,
consectetur adipiscing elit. Cras rutrum neque odio, vel viverra lectus vulputate et.
</Text>
<ProductPrice
currency="USD"
price={ 24.92 }
offPrice={ 12.42 }
showNotOffPrice={ true }
isNotConvenientPrice={ false }
hidePriceFraction={ false }
hideDiscountLabel={ false }
promoLabel="NEW"
legend="/month, paid yearly"
/>
</div>
),
triggerButton: 'Open Modal',
hideCloseButton: false,
buttonContent: 'Upgrade now',
secondaryColumn: <img src={ boostImage } alt="Boost" />,
buttonExternalLink: 'https://jetpack.com',
};

const Template = args => (
<HashRouter>
<Routes>
<Route path="/" element={ <ProductInterstitialModal { ...args } /> } />
</Routes>
</HashRouter>
);

export const Default = Template.bind( {} );

export const WithAdditionalColumn = Template.bind( {} );
WithAdditionalColumn.args = {
...DefaultArgs,
secondaryColumn: <div>CTA Content</div>,
additionalColumn: <div>Additional Column</div>,
};

Default.parameters = {};
Default.args = DefaultArgs;
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.component-product-interstitial-modal {
:global(.components-modal__header) + div {
height: 100%;
}
}


.wrapper {
height: 100%;
}

.primary {
display: flex;
flex-direction: column;
justify-content: space-between;
}

.primary-content {
display: flex;
flex-direction: column;
justify-content: space-between;
}

.primary-footer {
display: flex;
flex-direction: row;
justify-content: space-between;
}

.secondary {
max-width: 100%;
height: auto;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;

img {
max-width: 100%;
height: auto;
max-height: 100%;
object-fit: contain;
display: flex;
align-items: center;
overflow: hidden;
}
}

.additional {
display: flex;
flex-direction: column;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: added

Adding new modal based interstitial component.

0 comments on commit 1b367b3

Please sign in to comment.