Update product editor CES modal to match new designs (#38592)
* Add new fields and copy update to product CES modal * Update styling for product CES modal * Record email in tracks callback if provided * Fix modal header spacing * Fix record callback types * Add optional tag styling * Allow submitting form when a reason has been selected * Fix modal padding bottom * Update modal width to match designs * Add changelog entries * Update margin for legend * Add props to doc comment * Make className prop optional * Update tests for recording score with email
This commit is contained in:
parent
0fc765beb3
commit
90e4ddbf29
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: add
|
||||||
|
|
||||||
|
Add props to allow passing a classname to the feedback modal
|
|
@ -5,6 +5,7 @@ import { createElement, useState } from '@wordpress/element';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Button, Modal } from '@wordpress/components';
|
import { Button, Modal } from '@wordpress/components';
|
||||||
import { Text } from '@woocommerce/experimental';
|
import { Text } from '@woocommerce/experimental';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a modal requesting customer feedback.
|
* Provides a modal requesting customer feedback.
|
||||||
|
@ -20,6 +21,7 @@ import { Text } from '@woocommerce/experimental';
|
||||||
* @param {string} props.cancelButtonLabel Label for the cancel button.
|
* @param {string} props.cancelButtonLabel Label for the cancel button.
|
||||||
* @param {Function} props.onModalClose Callback for when user closes modal by clicking cancel.
|
* @param {Function} props.onModalClose Callback for when user closes modal by clicking cancel.
|
||||||
* @param {Function} props.children Children to be rendered.
|
* @param {Function} props.children Children to be rendered.
|
||||||
|
* @param {string} props.className Class name to addd to the modal.
|
||||||
*/
|
*/
|
||||||
function FeedbackModal( {
|
function FeedbackModal( {
|
||||||
onSubmit,
|
onSubmit,
|
||||||
|
@ -30,6 +32,7 @@ function FeedbackModal( {
|
||||||
isSubmitButtonDisabled,
|
isSubmitButtonDisabled,
|
||||||
submitButtonLabel,
|
submitButtonLabel,
|
||||||
cancelButtonLabel,
|
cancelButtonLabel,
|
||||||
|
className,
|
||||||
}: {
|
}: {
|
||||||
onSubmit: () => void;
|
onSubmit: () => void;
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -39,6 +42,7 @@ function FeedbackModal( {
|
||||||
isSubmitButtonDisabled?: boolean;
|
isSubmitButtonDisabled?: boolean;
|
||||||
submitButtonLabel?: string;
|
submitButtonLabel?: string;
|
||||||
cancelButtonLabel?: string;
|
cancelButtonLabel?: string;
|
||||||
|
className?: string;
|
||||||
} ): JSX.Element | null {
|
} ): JSX.Element | null {
|
||||||
const [ isOpen, setOpen ] = useState( true );
|
const [ isOpen, setOpen ] = useState( true );
|
||||||
|
|
||||||
|
@ -55,21 +59,23 @@ function FeedbackModal( {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
className="woocommerce-feedback-modal"
|
className={ classnames( 'woocommerce-feedback-modal', className ) }
|
||||||
title={ title }
|
title={ title }
|
||||||
onRequestClose={ closeModal }
|
onRequestClose={ closeModal }
|
||||||
shouldCloseOnClickOutside={ false }
|
shouldCloseOnClickOutside={ false }
|
||||||
>
|
>
|
||||||
<Text
|
{ description && (
|
||||||
variant="body"
|
<Text
|
||||||
as="p"
|
variant="body"
|
||||||
className="woocommerce-feedback-modal__description"
|
as="p"
|
||||||
size={ 14 }
|
className="woocommerce-feedback-modal__description"
|
||||||
lineHeight="20px"
|
size={ 14 }
|
||||||
marginBottom="1.5em"
|
lineHeight="20px"
|
||||||
>
|
marginBottom="1.5em"
|
||||||
{ description }
|
>
|
||||||
</Text>
|
{ description }
|
||||||
|
</Text>
|
||||||
|
) }
|
||||||
{ children }
|
{ children }
|
||||||
<div className="woocommerce-feedback-modal__buttons">
|
<div className="woocommerce-feedback-modal__buttons">
|
||||||
<Button isTertiary onClick={ closeModal } name="cancel">
|
<Button isTertiary onClick={ closeModal } name="cancel">
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: update
|
||||||
|
|
||||||
|
Update product CES modal design and fields
|
|
@ -41,11 +41,16 @@ export const ProductMVPFeedbackModalContainer: React.FC< {
|
||||||
`post-new.php?post_type=product&product_block_editor=0&_feature_nonce=${ _feature_nonce }`
|
`post-new.php?post_type=product&product_block_editor=0&_feature_nonce=${ _feature_nonce }`
|
||||||
);
|
);
|
||||||
|
|
||||||
const recordScore = ( checked: string[], comments: string ) => {
|
const recordScore = (
|
||||||
|
checked: string[],
|
||||||
|
comments: string,
|
||||||
|
email: string
|
||||||
|
) => {
|
||||||
recordEvent( 'product_mvp_feedback', {
|
recordEvent( 'product_mvp_feedback', {
|
||||||
action: 'disable',
|
action: 'disable',
|
||||||
checked,
|
checked,
|
||||||
comments: comments || '',
|
comments: comments || '',
|
||||||
|
email,
|
||||||
} );
|
} );
|
||||||
hideProductMVPFeedbackModal();
|
hideProductMVPFeedbackModal();
|
||||||
window.location.href = `${ classicEditorUrl }&new-product-experience-disabled=true`;
|
window.location.href = `${ classicEditorUrl }&new-product-experience-disabled=true`;
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { createElement, Fragment, useState } from '@wordpress/element';
|
import {
|
||||||
|
createElement,
|
||||||
|
createInterpolateElement,
|
||||||
|
Fragment,
|
||||||
|
useState,
|
||||||
|
} from '@wordpress/element';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { CheckboxControl, TextareaControl } from '@wordpress/components';
|
import {
|
||||||
|
CheckboxControl,
|
||||||
|
TextareaControl,
|
||||||
|
TextControl,
|
||||||
|
} from '@wordpress/components';
|
||||||
import { FeedbackModal } from '@woocommerce/customer-effort-score';
|
import { FeedbackModal } from '@woocommerce/customer-effort-score';
|
||||||
import { Text } from '@woocommerce/experimental';
|
import { Text } from '@woocommerce/experimental';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
|
@ -20,7 +29,11 @@ function ProductMVPFeedbackModal( {
|
||||||
recordScoreCallback,
|
recordScoreCallback,
|
||||||
onCloseModal,
|
onCloseModal,
|
||||||
}: {
|
}: {
|
||||||
recordScoreCallback: ( checked: string[], comments: string ) => void;
|
recordScoreCallback: (
|
||||||
|
checked: string[],
|
||||||
|
comments: string,
|
||||||
|
email: string
|
||||||
|
) => void;
|
||||||
onCloseModal?: () => void;
|
onCloseModal?: () => void;
|
||||||
} ): JSX.Element | null {
|
} ): JSX.Element | null {
|
||||||
const [ missingFeatures, setMissingFeatures ] = useState( false );
|
const [ missingFeatures, setMissingFeatures ] = useState( false );
|
||||||
|
@ -61,37 +74,33 @@ function ProductMVPFeedbackModal( {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const [ comments, setComments ] = useState( '' );
|
const [ comments, setComments ] = useState( '' );
|
||||||
|
const [ email, setEmail ] = useState( '' );
|
||||||
|
const checked = checkboxes
|
||||||
|
.filter( ( checkbox ) => checkbox.checked )
|
||||||
|
.map( ( checkbox ) => checkbox.key );
|
||||||
|
|
||||||
const onSendFeedback = () => {
|
const onSendFeedback = () => {
|
||||||
const checked = checkboxes
|
recordScoreCallback( checked, comments, email );
|
||||||
.filter( ( checkbox ) => checkbox.checked )
|
|
||||||
.map( ( checkbox ) => checkbox.key );
|
|
||||||
recordScoreCallback( checked, comments );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const isSendButtonDisabled =
|
const optionalElement = (
|
||||||
! comments &&
|
<span className="woocommerce-product-mvp-feedback-modal__optional">
|
||||||
! missingFeatures &&
|
{ __( '(optional)', 'woocommerce' ) }
|
||||||
! missingPlugins &&
|
</span>
|
||||||
! difficultToUse &&
|
);
|
||||||
! slowBuggyOrBroken &&
|
|
||||||
! other;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FeedbackModal
|
<FeedbackModal
|
||||||
title={ __(
|
title={ __(
|
||||||
'Thanks for trying out the new product editor!',
|
'Thanks for trying out the new product form!',
|
||||||
'woocommerce'
|
|
||||||
) }
|
|
||||||
description={ __(
|
|
||||||
'We’re working on making it better, and your feedback will help improve the experience for thousands of merchants like you.',
|
|
||||||
'woocommerce'
|
'woocommerce'
|
||||||
) }
|
) }
|
||||||
onSubmit={ onSendFeedback }
|
onSubmit={ onSendFeedback }
|
||||||
onModalClose={ onCloseModal }
|
onModalClose={ onCloseModal }
|
||||||
isSubmitButtonDisabled={ isSendButtonDisabled }
|
isSubmitButtonDisabled={ ! checked.length }
|
||||||
submitButtonLabel={ __( 'Send feedback', 'woocommerce' ) }
|
submitButtonLabel={ __( 'Send feedback', 'woocommerce' ) }
|
||||||
cancelButtonLabel={ __( 'Skip', 'woocommerce' ) }
|
cancelButtonLabel={ __( 'Skip', 'woocommerce' ) }
|
||||||
|
className="woocommerce-product-mvp-feedback-modal"
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
<Text
|
<Text
|
||||||
|
@ -100,45 +109,63 @@ function ProductMVPFeedbackModal( {
|
||||||
weight="600"
|
weight="600"
|
||||||
size="14"
|
size="14"
|
||||||
lineHeight="20px"
|
lineHeight="20px"
|
||||||
>
|
></Text>
|
||||||
{ __(
|
<fieldset className="woocommerce-product-mvp-feedback-modal__reason">
|
||||||
'What made you switch back to the classic product editor?',
|
<legend>
|
||||||
'woocommerce'
|
{ __(
|
||||||
) }
|
'What made you turn off the new product form?',
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
weight="400"
|
|
||||||
size="12"
|
|
||||||
as="p"
|
|
||||||
lineHeight="16px"
|
|
||||||
color="#757575"
|
|
||||||
className="woocommerce-product-mvp-feedback-modal__subtitle"
|
|
||||||
>
|
|
||||||
{ __( '(Check all that apply)', 'woocommerce' ) }
|
|
||||||
</Text>
|
|
||||||
<div className="woocommerce-product-mvp-feedback-modal__checkboxes">
|
|
||||||
{ checkboxes.map( ( checkbox, index ) => (
|
|
||||||
<CheckboxControl
|
|
||||||
key={ index }
|
|
||||||
label={ checkbox.label }
|
|
||||||
name={ checkbox.key }
|
|
||||||
checked={ checkbox.checked }
|
|
||||||
onChange={ checkbox.onChange }
|
|
||||||
/>
|
|
||||||
) ) }
|
|
||||||
</div>
|
|
||||||
<div className="woocommerce-product-mvp-feedback-modal__comments">
|
|
||||||
<TextareaControl
|
|
||||||
label={ __( 'Additional comments', 'woocommerce' ) }
|
|
||||||
value={ comments }
|
|
||||||
placeholder={ __(
|
|
||||||
'Optional, but much apprecated. We love reading your feedback!',
|
|
||||||
'woocommerce'
|
'woocommerce'
|
||||||
) }
|
) }
|
||||||
|
</legend>
|
||||||
|
<div className="woocommerce-product-mvp-feedback-modal__checkboxes">
|
||||||
|
{ checkboxes.map( ( checkbox, index ) => (
|
||||||
|
<CheckboxControl
|
||||||
|
key={ index }
|
||||||
|
label={ checkbox.label }
|
||||||
|
name={ checkbox.key }
|
||||||
|
checked={ checkbox.checked }
|
||||||
|
onChange={ checkbox.onChange }
|
||||||
|
/>
|
||||||
|
) ) }
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<div className="woocommerce-product-mvp-feedback-modal__comments">
|
||||||
|
<TextareaControl
|
||||||
|
label={ createInterpolateElement(
|
||||||
|
__(
|
||||||
|
'Additional thoughts <optional/>',
|
||||||
|
'woocommerce'
|
||||||
|
),
|
||||||
|
{
|
||||||
|
optional: optionalElement,
|
||||||
|
}
|
||||||
|
) }
|
||||||
|
value={ comments }
|
||||||
onChange={ ( value: string ) => setComments( value ) }
|
onChange={ ( value: string ) => setComments( value ) }
|
||||||
rows={ 5 }
|
rows={ 5 }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="woocommerce-product-mvp-feedback-modal__email">
|
||||||
|
<TextControl
|
||||||
|
label={ createInterpolateElement(
|
||||||
|
__(
|
||||||
|
'Your email address <optional/>',
|
||||||
|
'woocommerce'
|
||||||
|
),
|
||||||
|
{
|
||||||
|
optional: optionalElement,
|
||||||
|
}
|
||||||
|
) }
|
||||||
|
value={ email }
|
||||||
|
onChange={ ( value: string ) => setEmail( value ) }
|
||||||
|
rows={ 5 }
|
||||||
|
help={ __(
|
||||||
|
'In case you want to participate in further discussion and future user research.',
|
||||||
|
'woocommerce'
|
||||||
|
) }
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
</FeedbackModal>
|
</FeedbackModal>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,23 +1,62 @@
|
||||||
|
$modal-header-height: 84px;
|
||||||
|
|
||||||
.woocommerce-product-mvp-feedback-modal {
|
.woocommerce-product-mvp-feedback-modal {
|
||||||
|
width: 600px;
|
||||||
|
|
||||||
|
.components-modal__header {
|
||||||
|
height: $modal-header-height;
|
||||||
|
|
||||||
|
&-heading {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.components-modal__content {
|
||||||
|
margin-top: $modal-header-height;
|
||||||
|
padding-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend,
|
||||||
|
label {
|
||||||
|
color: $gray-900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.woocommerce-product-mvp-feedback-modal__optional {
|
||||||
|
color: $gray-700;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.4;
|
||||||
|
text-transform: uppercase;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: $gap-small;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
&__subtitle {
|
&__subtitle {
|
||||||
margin-top: $gap-smaller !important;
|
margin-top: $gap-smaller !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__checkboxes {
|
&__checkboxes {
|
||||||
margin: $gap-small 0;
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__comments {
|
&__comments {
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
margin-bottom: 1.5em;
|
margin-bottom: 1.5em;
|
||||||
|
|
||||||
label {
|
|
||||||
display: block;
|
|
||||||
font-weight: bold;
|
|
||||||
text-transform: none;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__reason,
|
||||||
|
&__comments,
|
||||||
|
&__email {
|
||||||
|
margin-bottom: $gap-large;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ describe( 'ProductMVPFeedbackModal', () => {
|
||||||
fireEvent.click( screen.getByRole( 'checkbox', { name: /other/i } ) );
|
fireEvent.click( screen.getByRole( 'checkbox', { name: /other/i } ) );
|
||||||
expect( mockRecordScoreCallback ).toHaveBeenCalledWith(
|
expect( mockRecordScoreCallback ).toHaveBeenCalledWith(
|
||||||
[ 'other' ],
|
[ 'other' ],
|
||||||
|
'',
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
|
|
Loading…
Reference in New Issue