Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replaced newsletter signup form in PNI product creep vote section with the new implementation approach #11791

Merged
merged 10 commits into from
Feb 6, 2024
35 changes: 25 additions & 10 deletions source/js/buyers-guide/components/creep-vote/creep-vote.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Component, Fragment } from "react";
import Creepometer from "../creepometer/creepometer.jsx";
import CreepChart from "../creepiness-chart/creepiness-chart.jsx";
import SocialShare from "../social-share/social-share.jsx";
import JoinUs from "../../../components/join/join.jsx";
import DefaultLayoutSignup from "../../../components/newsletter-signup/organisms/default-layout-signup.jsx";
import { getText } from "../../../components/petition/locales";

import CREEPINESS_LABELS from "../creepiness-labels.js";
Expand Down Expand Up @@ -226,15 +226,30 @@ class CreepVote extends Component {
>
Close
</button>
<JoinUs
formPosition="flow"
flowHeading={getText(`You voted! You rock!`)}
flowText={getText(
`Now that you’re on a roll, why not join Mozilla? We’re not creepy (we promise). We actually fight back against creepy. And we need more people like you.`
)}
apiUrl={this.props.joinUsApiUrl}
handleSignUp={(successState) => this.handleSignUp(successState)}
/>
<div className="medium:tw-mx-12">
<DefaultLayoutSignup
formPosition="pni-product-quiz"
formStyle="pni-creep-vote"
showCountryFieldByDefault="true"
showLanguageFieldByDefault="true"
ctaHeader={getText(`You voted! You rock!`)}
ctaDescription={
<p>
{getText(`Now that you’re on a roll, why not join Mozilla? We’re
not creepy (we promise). We actually fight back against creepy.
And we need more people like you.`)}
</p>
}
apiUrl={this.props.joinUsApiUrl}
showQuitButton="true"
handleQuitButtonClick={(successState) =>
this.handleSignUp(successState)
}
handleSubmissionSuccess={(successState) =>
this.handleSignUp(successState)
}
/>
</div>
</Fragment>
);
}
Expand Down
62 changes: 5 additions & 57 deletions source/js/components/join/join.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,6 @@ class JoinUs extends Component {
* Render the signup CTA.
*/
render() {
if (this.state.apiSuccess && this.state.apiSubmitted && this.isFlowForm()) {
this.props.handleSignUp(true);
}

let signupState = classNames({
"signup-success": this.state.apiSuccess && this.state.apiSubmitted,
"signup-fail": !this.state.apiFailed && this.state.apiSubmitted,
Expand All @@ -266,7 +262,6 @@ class JoinUs extends Component {
"col-md-6": this.props.layout === `2-column` && !this.state.apiSuccess,
"col-sm-12 col-md-8":
this.props.layout === `2-column` && this.state.apiSuccess,
"col-md-11 m-auto": this.isFlowForm(),
});

return (
Expand All @@ -277,24 +272,6 @@ class JoinUs extends Component {
);
}

isFlowForm() {
return this.props.formPosition === "flow";
}

/**
* Render the CTA heading.
*/
renderFlowHeading() {
return [
<h2 className="tw-h3-heading text-center" key={`flowheading`}>
{this.props.flowHeading}
</h2>,
<p className="text-center" key={`flowheadingpara`}>
{this.props.flowText}
</p>,
];
}

/**
* Render the CTA heading.
*/
Expand Down Expand Up @@ -346,9 +323,6 @@ class JoinUs extends Component {
* Render the CTA heading.
*/
renderFormHeading() {
if (this.isFlowForm()) {
return this.renderFlowHeading();
}
return this.renderSnippetHeading();
}

Expand Down Expand Up @@ -382,18 +356,11 @@ class JoinUs extends Component {
"tw-h-24": this.props.formStyle == `pni`,
});

let errorWrapperClasses = classNames("glyph-container", {
"d-none": this.isFlowForm(),
});
let errorWrapperClasses = "glyph-container";

return (
<div className={wrapperClasses}>
<div className={classes}>
{this.isFlowForm() && (
<label className="font-weight-bold" htmlFor={this.id.userEmail}>
Email
</label>
)}
<input
name="userEmail"
type="email"
Expand All @@ -402,7 +369,7 @@ class JoinUs extends Component {
ref={(el) => (this.email = el)}
onFocus={(evt) => this.onInputFocus(evt)}
onInput={(evt) => this.toggleSubmitButton(evt)}
aria-label={!this.isFlowForm() ? "Email" : ""}
aria-label="Email"
id={this.id.userEmail}
/>
{this.state.userTriedSubmitting && !emailValidation.valid && (
Expand Down Expand Up @@ -526,8 +493,7 @@ class JoinUs extends Component {
</label>
{this.state.userTriedSubmitting &&
!this.state.apiSubmitted &&
!this.privacy.checked &&
!this.isFlowForm() && (
!this.privacy.checked && (
<span className="tw-form-error-glyph tw-flex tw-ml-2" />
)}
</div>
Expand Down Expand Up @@ -561,10 +527,7 @@ class JoinUs extends Component {
);
buttonText = getText("Sign up");
} else {
classnames = classNames("tw-btn", "tw-btn-primary", {
"w-100": !this.isFlowForm(),
"tw-flex-1 tw-mr-8": this.isFlowForm(),
});
classnames = "tw-btn tw-btn-primary w-100";
buttonText = getText("Sign up");
}

Expand Down Expand Up @@ -596,10 +559,6 @@ class JoinUs extends Component {
buttonsWrapperClass = `ml-md-3`;
}

if (this.props.formPosition === `flow`) {
buttonsWrapperClass = `d-flex`;
}

if (this.props.formStyle === `pop`) {
buttonsWrapperClass = `w-auto tw-text-right`;
}
Expand All @@ -622,18 +581,7 @@ class JoinUs extends Component {
{this.renderLocaleFields()}
{this.renderPrivacyField()}
</div>
<div className={buttonsWrapperClass}>
{this.renderSubmitButton()}
{this.isFlowForm() && (
<button
className="tw-btn tw-btn-primary btn-dismiss tw-flex-1"
onClick={() => this.props.handleSignUp(false)}
type="button"
>
No thanks
</button>
)}
</div>
<div className={buttonsWrapperClass}>{this.renderSubmitButton()}</div>
</form>
);
}
Expand Down
34 changes: 34 additions & 0 deletions source/js/components/newsletter-signup/atoms/button-quit.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from "react";
import classNames from "classnames";
import PropTypes from "prop-types";

const ButtonQuit = ({
children,
buttonStyle = "primary",
widthClasses = `tw-w-full`,
handleQuitButtonClick,
}) => {
// [TODO]
// Ideally styling for this "atom" component should be pre-defined in a Tailwind config file.
// Because our design system still needs to be finalized,
// we are using hardcoded Tailwind classes directly here for now.
let classes = classNames(
`tw-btn tw-btn-${buttonStyle} btn-dismiss`,
widthClasses
);

return (
<button type="button" className={classes} onClick={handleQuitButtonClick}>
{children}
</button>
);
};

ButtonQuit.propTypes = {
children: PropTypes.node.isRequired,
buttonStyle: PropTypes.oneOf(["primary", "secondary"]),
widthClasses: PropTypes.string,
handleQuitButtonClick: PropTypes.func.isRequired,
};

export default ButtonQuit;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import InputText from "../atoms/input-text.jsx";
import Select from "../atoms/select.jsx";
import InputCheckboxWithLabel from "../molecules/input-checkbox-with-label.jsx";
import ButtonSubmit from "../atoms/button-submit.jsx";
import ButtonQuit from "../atoms/button-quit.jsx";
import withSubmissionLogic from "./with-submission-logic.jsx";
import utility from "../../../utility.js";
import { ReactGA } from "../../../common";
Expand Down Expand Up @@ -47,7 +48,8 @@ class DefaultSignupForm extends Component {
showCountryField:
this.props.showCountryFieldByDefault?.toLowerCase() === "true",
showLanguageField:
this.props.showCountryFieldByDefault?.toLowerCase() === "true",
this.props.showLanguageFieldByDefault?.toLowerCase() === "true",
mmmavis marked this conversation as resolved.
Show resolved Hide resolved
showQuitButton: this.props.showQuitButton?.toLowerCase() === "true",
submitButtonDisabled: this.props.disableSubmitButtonByDefault,
};
}
Expand Down Expand Up @@ -268,6 +270,43 @@ class DefaultSignupForm extends Component {
);
}

renderButtons() {
let wrapperClasses = classNames({
"tw-flex-shrink-0 tw-mt-8 medium:tw-mt-0":
this.style.buttonPosition !== "bottom",
"tw-mt-24 medium:tw-mt-12 tw-text-right":
this.style.buttonPosition === "bottom",
});

let submitButton = (
<ButtonSubmit
buttonStyle={this.style.buttonStyle}
widthClasses={this.style.buttonWidthClasses}
disabled={this.state.submitButtonDisabled}
>
{this.buttonText}
</ButtonSubmit>
);

let buttons = submitButton;

if (this.state.showQuitButton) {
buttons = (
<div className="tw-flex tw-gap-x-4">
{submitButton}
<ButtonQuit
widthClasses={this.style.buttonWidthClasses}
handleQuitButtonClick={this.props.handleQuitButtonClick}
>
{getText(`No thanks`)}
</ButtonQuit>
</div>
);
}

return <div className={wrapperClasses}>{buttons}</div>;
}

renderForm() {
if (this.props.hideForm) return null;

Expand All @@ -276,13 +315,6 @@ class DefaultSignupForm extends Component {
this.style.buttonPosition !== "bottom",
});

let buttonWrapperClasses = classNames({
"tw-flex-shrink-0 tw-mt-8 medium:tw-mt-0":
this.style.buttonPosition !== "bottom",
"tw-mt-24 medium:tw-mt-12 tw-text-right":
this.style.buttonPosition === "bottom",
});

return (
<form
noValidate={this.props.noBrowserValidation}
Expand All @@ -299,16 +331,7 @@ class DefaultSignupForm extends Component {
</fieldset>
<fieldset>{this.renderPrivacyCheckbox()}</fieldset>
</div>
<div className={buttonWrapperClasses}>
<ButtonSubmit
buttonStyle={this.style.buttonStyle}
widthClasses={this.style.buttonWidthClasses}
disabled={this.state.submitButtonDisabled}
buttonCtaEvent={this.props.buttonCtaEvent}
>
{this.buttonText}
</ButtonSubmit>
</div>
{this.renderButtons()}
</div>
</form>
);
Expand Down Expand Up @@ -341,6 +364,9 @@ DefaultSignupForm.propTypes = {
onSubmit: PropTypes.func.isRequired,
noBrowserValidation: PropTypes.bool,
hideForm: PropTypes.bool,
showCountryFieldByDefault: PropTypes.string,
showLanguageFieldByDefault: PropTypes.string,
showQuitButton: PropTypes.string,
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ export const FORM_STYLE = {
descriptionClass: `medium:tw-w-4/5`,
headingClass: "tw-h3-heading",
},
"pni-creep-vote": {
buttonPosition: "bottom",
buttonStyle: "primary",
buttonWidthClasses: "tw-w-1/2",
descriptionClass: "tw-text-center",
fieldStyle: "filled",
headingLevel: 2,
headingClass: "tw-h3-heading tw-text-center",
},
"pni-product-quiz": {
fieldStyle: "filled",
headingLevel: 4,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,8 @@ function withSubmissionLogic(WrappedComponent) {
WithSubmissionLogicComponent.propTypes = {
apiUrl: PropTypes.string.isRequired,
ctaHeader: PropTypes.string.isRequired,
ctaDescription: PropTypes.string.isRequired,
ctaDescription: PropTypes.oneOfType([PropTypes.string, PropTypes.node])
.isRequired,
formPosition: PropTypes.string,
whenLoaded: PropTypes.func,
};
Expand Down
Loading