Merge pull request #3265 from benjiwheeler/join-flow-email-improve

Join flow email improvements
This commit is contained in:
Benjamin Wheeler 2019-08-19 16:22:33 +02:00 committed by GitHub
commit 4a01fabff8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 45 additions and 35 deletions

View file

@ -8,19 +8,16 @@ require('./formik-forms.scss');
require('../forms/row.scss'); require('../forms/row.scss');
const FormikCheckboxSubComponent = ({ const FormikCheckboxSubComponent = ({
className,
field, field,
id, id,
label, label,
labelClassName,
...props ...props
}) => ( }) => (
<div className="checkbox"> <div className="checkbox">
<input <input
checked={field.value} checked={field.value}
className={classNames( className="formik-checkbox"
'formik-checkbox',
className
)}
id={id} id={id}
name={field.name} name={field.name}
type="checkbox" type="checkbox"
@ -32,8 +29,9 @@ const FormikCheckboxSubComponent = ({
{label && ( {label && (
<label <label
className={classNames( className={classNames(
'formik-checkbox-label',
'formik-label', 'formik-label',
'formik-checkbox-label' labelClassName
)} )}
htmlFor={id} htmlFor={id}
> >
@ -44,7 +42,6 @@ const FormikCheckboxSubComponent = ({
); );
FormikCheckboxSubComponent.propTypes = { FormikCheckboxSubComponent.propTypes = {
className: PropTypes.string,
field: PropTypes.shape({ field: PropTypes.shape({
name: PropTypes.string, name: PropTypes.string,
onBlur: PropTypes.function, onBlur: PropTypes.function,
@ -52,31 +49,32 @@ FormikCheckboxSubComponent.propTypes = {
value: PropTypes.bool value: PropTypes.bool
}), }),
id: PropTypes.string, id: PropTypes.string,
label: PropTypes.string label: PropTypes.string,
labelClassName: PropTypes.string
}; };
const FormikCheckbox = ({ const FormikCheckbox = ({
className,
id, id,
label, label,
labelClassName,
name, name,
...props ...props
}) => ( }) => (
<Field <Field
className={className}
component={FormikCheckboxSubComponent} component={FormikCheckboxSubComponent}
id={id} id={id}
label={label} label={label}
labelClassName={labelClassName}
name={name} name={name}
{...props} {...props}
/> />
); );
FormikCheckbox.propTypes = { FormikCheckbox.propTypes = {
className: PropTypes.string,
id: PropTypes.string, id: PropTypes.string,
label: PropTypes.string, label: PropTypes.string,
labelClassName: PropTypes.string,
name: PropTypes.string name: PropTypes.string
}; };

View file

@ -1,9 +1,5 @@
@import "../../colors"; @import "../../colors";
.formik-checkbox-label {
font-weight: 300;
}
input[type="checkbox"].formik-checkbox { input[type="checkbox"].formik-checkbox {
display: block; display: block;
float: left; float: left;
@ -14,16 +10,12 @@ input[type="checkbox"].formik-checkbox {
height: 1.25rem; height: 1.25rem;
appearance: none; appearance: none;
&:focus:checked { &:focus {
transition: all .5s ease; transition: all .25s ease;
outline: none; outline: none;
box-shadow: 0 0 0 .25rem $ui-blue-25percent; box-shadow: 0 0 0 .25rem $ui-blue-25percent;
} }
&:focus:not(:checked) {
outline: none;
}
&:checked { &:checked {
background-color: $ui-blue; background-color: $ui-blue;
text-align: center; text-align: center;

View file

@ -25,4 +25,9 @@
outline: none; outline: none;
} }
} }
&::placeholder {
font-style: italic;
color: $type-gray-75percent;
}
} }

View file

@ -1,7 +0,0 @@
@import "../../colors";
@import "../../frameless";
.input::placeholder {
font-style: italic;
color: $type-gray-75percent;
}

View file

@ -9,6 +9,7 @@ const FormattedMessage = require('react-intl').FormattedMessage;
const JoinFlowStep = require('./join-flow-step.jsx'); const JoinFlowStep = require('./join-flow-step.jsx');
const FormikInput = require('../../components/formik-forms/formik-input.jsx'); const FormikInput = require('../../components/formik-forms/formik-input.jsx');
const FormikCheckbox = require('../../components/formik-forms/formik-checkbox.jsx');
require('./join-flow-steps.scss'); require('./join-flow-steps.scss');
@ -17,12 +18,12 @@ class EmailStep extends React.Component {
super(props); super(props);
bindAll(this, [ bindAll(this, [
'handleValidSubmit', 'handleValidSubmit',
'validateEmailIfPresent', 'validateEmail',
'validateForm' 'validateForm'
]); ]);
} }
validateEmailIfPresent (email) { validateEmail (email) {
if (!email) return null; // skip validation if email is blank; null indicates valid if (!email) return this.props.intl.formatMessage({id: 'general.required'});
const isValidLocally = emailValidator.validate(email); const isValidLocally = emailValidator.validate(email);
if (isValidLocally) { if (isValidLocally) {
return null; // TODO: validate email address remotely return null; // TODO: validate email address remotely
@ -51,6 +52,7 @@ class EmailStep extends React.Component {
errors, errors,
handleSubmit, handleSubmit,
isSubmitting, isSubmitting,
setFieldError,
validateField validateField
} = props; } = props;
return ( return (
@ -89,10 +91,20 @@ class EmailStep extends React.Component {
id="email" id="email"
name="email" name="email"
placeholder={this.props.intl.formatMessage({id: 'general.emailAddress'})} placeholder={this.props.intl.formatMessage({id: 'general.emailAddress'})}
validate={this.validateEmailIfPresent} validate={this.validateEmail}
validationClassName="validation-full-width-input" validationClassName="validation-full-width-input"
onBlur={() => validateField('email')} // eslint-disable-line react/jsx-no-bind /* eslint-disable react/jsx-no-bind */
onBlur={() => validateField('email')}
onFocus={() => setFieldError('email', null)}
/* eslint-enable react/jsx-no-bind */
/> />
<div className="join-flow-email-checkbox-row">
<FormikCheckbox
id="subscribeCheckbox"
label={this.props.intl.formatMessage({id: 'registration.receiveEmails'})}
name="subscribe"
/>
</div>
</JoinFlowStep> </JoinFlowStep>
); );
}} }}

View file

@ -129,6 +129,15 @@
margin-left: .5rem; margin-left: .5rem;
} }
.modal-inner-content-email {
padding-top: 2.9rem;
}
.join-flow-email-checkbox-row {
font-size: .75rem;
margin: .25rem .125rem;
}
a.join-flow-link:link, a.join-flow-link:visited, a.join-flow-link:active { a.join-flow-link:link, a.join-flow-link:visited, a.join-flow-link:active {
text-decoration: underline; text-decoration: underline;
} }

View file

@ -159,7 +159,7 @@
"registration.classroomInviteNewStudentStepDescription": "Your teacher has invited you to join a class:", "registration.classroomInviteNewStudentStepDescription": "Your teacher has invited you to join a class:",
"registration.confirmYourEmail": "Confirm Your Email", "registration.confirmYourEmail": "Confirm Your Email",
"registration.confirmYourEmailDescription": "If you haven't already, please click the link in the confirmation email sent to:", "registration.confirmYourEmailDescription": "If you haven't already, please click the link in the confirmation email sent to:",
"registration.createAccount": "Create Account", "registration.createAccount": "Create Your Account",
"registration.createUsername": "Create a username", "registration.createUsername": "Create a username",
"registration.genderStepTitle": "What's your gender?", "registration.genderStepTitle": "What's your gender?",
"registration.genderStepDescription": "Scratch welcomes people of all genders. We will always keep this information private.", "registration.genderStepDescription": "Scratch welcomes people of all genders. We will always keep this information private.",
@ -182,6 +182,7 @@
"registration.personalStepTitle": "Personal Information", "registration.personalStepTitle": "Personal Information",
"registration.personalStepDescription": "Your individual responses will not be displayed publicly, and will be kept confidential and secure", "registration.personalStepDescription": "Your individual responses will not be displayed publicly, and will be kept confidential and secure",
"registration.private": "Scratch will always keep this information private.", "registration.private": "Scratch will always keep this information private.",
"registration.receiveEmails": "I'd like to receive emails from the Scratch Team about project ideas, events, and more.",
"registration.selectCountry": "select country", "registration.selectCountry": "select country",
"registration.studentPersonalStepDescription": "This information will not appear on the Scratch website.", "registration.studentPersonalStepDescription": "This information will not appear on the Scratch website.",
"registration.showPassword": "Show password", "registration.showPassword": "Show password",
@ -192,7 +193,7 @@
"registration.studentUsernameStepHelpText": "Already have a Scratch account?", "registration.studentUsernameStepHelpText": "Already have a Scratch account?",
"registration.studentUsernameStepTooltip": "You'll need to create a new Scratch account to join this class.", "registration.studentUsernameStepTooltip": "You'll need to create a new Scratch account to join this class.",
"registration.studentUsernameFieldHelpText": "For safety, don't use your real name!", "registration.studentUsernameFieldHelpText": "For safety, don't use your real name!",
"registration.acceptTermsOfUse": "By creating an account, I accept and agree to the {touLink}.", "registration.acceptTermsOfUse": "By creating an account, you accept and agree to the {touLink}.",
"registration.usernameStepTitle": "Request a Teacher Account", "registration.usernameStepTitle": "Request a Teacher Account",
"registration.usernameStepTitleScratcher": "Create a Scratch Account", "registration.usernameStepTitleScratcher": "Create a Scratch Account",
"registration.validationMaxLength": "Sorry, you have exceeded the maximum character limit.", "registration.validationMaxLength": "Sorry, you have exceeded the maximum character limit.",