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:
Joshua T Flowers 2023-06-12 10:58:00 -07:00 committed by GitHub
parent 0fc765beb3
commit 90e4ddbf29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 159 additions and 73 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add props to allow passing a classname to the feedback modal

View File

@ -5,6 +5,7 @@ import { createElement, useState } from '@wordpress/element';
import PropTypes from 'prop-types';
import { Button, Modal } from '@wordpress/components';
import { Text } from '@woocommerce/experimental';
import classnames from 'classnames';
/**
* 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 {Function} props.onModalClose Callback for when user closes modal by clicking cancel.
* @param {Function} props.children Children to be rendered.
* @param {string} props.className Class name to addd to the modal.
*/
function FeedbackModal( {
onSubmit,
@ -30,6 +32,7 @@ function FeedbackModal( {
isSubmitButtonDisabled,
submitButtonLabel,
cancelButtonLabel,
className,
}: {
onSubmit: () => void;
title: string;
@ -39,6 +42,7 @@ function FeedbackModal( {
isSubmitButtonDisabled?: boolean;
submitButtonLabel?: string;
cancelButtonLabel?: string;
className?: string;
} ): JSX.Element | null {
const [ isOpen, setOpen ] = useState( true );
@ -55,21 +59,23 @@ function FeedbackModal( {
return (
<Modal
className="woocommerce-feedback-modal"
className={ classnames( 'woocommerce-feedback-modal', className ) }
title={ title }
onRequestClose={ closeModal }
shouldCloseOnClickOutside={ false }
>
<Text
variant="body"
as="p"
className="woocommerce-feedback-modal__description"
size={ 14 }
lineHeight="20px"
marginBottom="1.5em"
>
{ description }
</Text>
{ description && (
<Text
variant="body"
as="p"
className="woocommerce-feedback-modal__description"
size={ 14 }
lineHeight="20px"
marginBottom="1.5em"
>
{ description }
</Text>
) }
{ children }
<div className="woocommerce-feedback-modal__buttons">
<Button isTertiary onClick={ closeModal } name="cancel">

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
Update product CES modal design and fields

View File

@ -41,11 +41,16 @@ export const ProductMVPFeedbackModalContainer: React.FC< {
`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', {
action: 'disable',
checked,
comments: comments || '',
email,
} );
hideProductMVPFeedbackModal();
window.location.href = `${ classicEditorUrl }&new-product-experience-disabled=true`;

View File

@ -1,9 +1,18 @@
/**
* External dependencies
*/
import { createElement, Fragment, useState } from '@wordpress/element';
import {
createElement,
createInterpolateElement,
Fragment,
useState,
} from '@wordpress/element';
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 { Text } from '@woocommerce/experimental';
import { __ } from '@wordpress/i18n';
@ -20,7 +29,11 @@ function ProductMVPFeedbackModal( {
recordScoreCallback,
onCloseModal,
}: {
recordScoreCallback: ( checked: string[], comments: string ) => void;
recordScoreCallback: (
checked: string[],
comments: string,
email: string
) => void;
onCloseModal?: () => void;
} ): JSX.Element | null {
const [ missingFeatures, setMissingFeatures ] = useState( false );
@ -61,37 +74,33 @@ function ProductMVPFeedbackModal( {
},
];
const [ comments, setComments ] = useState( '' );
const [ email, setEmail ] = useState( '' );
const checked = checkboxes
.filter( ( checkbox ) => checkbox.checked )
.map( ( checkbox ) => checkbox.key );
const onSendFeedback = () => {
const checked = checkboxes
.filter( ( checkbox ) => checkbox.checked )
.map( ( checkbox ) => checkbox.key );
recordScoreCallback( checked, comments );
recordScoreCallback( checked, comments, email );
};
const isSendButtonDisabled =
! comments &&
! missingFeatures &&
! missingPlugins &&
! difficultToUse &&
! slowBuggyOrBroken &&
! other;
const optionalElement = (
<span className="woocommerce-product-mvp-feedback-modal__optional">
{ __( '(optional)', 'woocommerce' ) }
</span>
);
return (
<FeedbackModal
title={ __(
'Thanks for trying out the new product editor!',
'woocommerce'
) }
description={ __(
'Were working on making it better, and your feedback will help improve the experience for thousands of merchants like you.',
'Thanks for trying out the new product form!',
'woocommerce'
) }
onSubmit={ onSendFeedback }
onModalClose={ onCloseModal }
isSubmitButtonDisabled={ isSendButtonDisabled }
isSubmitButtonDisabled={ ! checked.length }
submitButtonLabel={ __( 'Send feedback', 'woocommerce' ) }
cancelButtonLabel={ __( 'Skip', 'woocommerce' ) }
className="woocommerce-product-mvp-feedback-modal"
>
<>
<Text
@ -100,45 +109,63 @@ function ProductMVPFeedbackModal( {
weight="600"
size="14"
lineHeight="20px"
>
{ __(
'What made you switch back to the classic product editor?',
'woocommerce'
) }
</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!',
></Text>
<fieldset className="woocommerce-product-mvp-feedback-modal__reason">
<legend>
{ __(
'What made you turn off the new product form?',
'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 ) }
rows={ 5 }
/>
</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>
);

View File

@ -1,23 +1,62 @@
$modal-header-height: 84px;
.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 {
margin-top: $gap-smaller !important;
}
&__checkboxes {
margin: $gap-small 0;
display: grid;
grid-template-columns: 1fr 1fr;
}
&__comments {
margin-top: 2em;
margin-bottom: 1.5em;
label {
display: block;
font-weight: bold;
text-transform: none;
font-size: 14px;
}
textarea {
width: 100%;
}
}
&__reason,
&__comments,
&__email {
margin-bottom: $gap-large;
}
}

View File

@ -48,6 +48,7 @@ describe( 'ProductMVPFeedbackModal', () => {
fireEvent.click( screen.getByRole( 'checkbox', { name: /other/i } ) );
expect( mockRecordScoreCallback ).toHaveBeenCalledWith(
[ 'other' ],
'',
''
);
} );