diff --git a/src/_style.scss b/src/_style.scss
index a3a6b70c..92d88382 100644
--- a/src/_style.scss
+++ b/src/_style.scss
@@ -14,6 +14,22 @@ $microsoft-focus-black: #000;
$apple-black: #000000;
$apple-focus-black: $apple-black;
+.sr-only {
+ position: absolute;
+ left: -10000px;
+ top: auto;
+ width: 1px;
+ height: 1px;
+ overflow: hidden;
+}
+
+.focus-out {
+ position: absolute;
+ padding-left: 17px;
+ opacity: 0.75;
+ z-index: 1;
+}
+
.alert-link {
font-weight: normal;
text-decoration: underline;
@@ -219,21 +235,21 @@ $apple-focus-black: $apple-black;
padding-left: 14px;
}
-.opt-inline-field{
- display: inline-block;
- width: 50%;
+.opt-inline-field {
+ display: inline-block;
+ width: 50%;
}
-.opt-year-field{
- padding-left: 15px;
+.opt-year-field {
+ padding-left: 15px;
}
.invalid-feedback {
color: $red;
}
-.full-vertical-height{
- height: 100vh;
+.full-vertical-height {
+ height: 100vh;
}
.help-links {
@@ -257,7 +273,7 @@ $apple-focus-black: $apple-black;
}
.mt-10 {
- margin-top: 10px;
+ margin-top: 10px;
}
.pt-10 {
@@ -281,7 +297,7 @@ $apple-focus-black: $apple-black;
.section-heading-line {
position: relative;
text-align: center;
-
+
&:before,
&:after {
width: 10%;
diff --git a/src/common-components/AuthnValidationFormGroup.jsx b/src/common-components/AuthnValidationFormGroup.jsx
index 8084eba8..a17b98d4 100644
--- a/src/common-components/AuthnValidationFormGroup.jsx
+++ b/src/common-components/AuthnValidationFormGroup.jsx
@@ -1,6 +1,5 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
-import { injectIntl } from '@edx/frontend-platform/i18n';
import {
Form,
Input,
@@ -11,13 +10,11 @@ const AuthnCustomValidationFormGroup = (props) => {
const { onClick, onChange, onBlur } = props;
const [showHelpText, setShowHelpText] = useState(false);
const [showLabelText, setShowLabelText] = useState(false);
- const [showPlaceholder, setShowPlaceHolder] = useState(true);
// handler code that need to be invoked via input
const onClickHandler = (e, clickCb) => {
setShowHelpText(true);
setShowLabelText(true);
- setShowPlaceHolder(false);
if (clickCb) {
clickCb(e);
}
@@ -25,7 +22,6 @@ const AuthnCustomValidationFormGroup = (props) => {
const onBlurHandler = (e, blurCb) => {
setShowHelpText(false);
setShowLabelText(false);
- setShowPlaceHolder(true);
if (blurCb) {
blurCb(e);
}
@@ -38,12 +34,18 @@ const AuthnCustomValidationFormGroup = (props) => {
const onOptionalHandler = (e, clickCb) => { clickCb(e); };
const showLabel = () => {
- const fieldLabel = (!props.optionalFieldCheckbox && showLabelText) ? (
-
- {props.label}
-
- ) : ;
- return fieldLabel;
+ let className;
+ if (props.optionalFieldCheckbox || (!showLabelText && (props.value !== '' || props.type === 'select'))) {
+ className = 'sr-only';
+ } else if (showLabelText) {
+ className = 'pt-10 h6';
+ } else {
+ className = 'pt-10 focus-out';
+ }
+
+ return (
+ {props.label}
+ );
};
const showOptional = () => {
const additionalField = props.optionalFieldCheckbox ? (
@@ -60,7 +62,6 @@ const AuthnCustomValidationFormGroup = (props) => {
type: props.type,
value: props.value,
};
- inputProps.placeholder = showPlaceholder ? props.label : '';
inputProps.onChange = (e) => onChangeHandler(e, onChange);
inputProps.onClick = (e) => onClickHandler(e, onClick);
inputProps.onBlur = (e) => onBlurHandler(e, onBlur);
@@ -145,4 +146,4 @@ AuthnCustomValidationFormGroup.propTypes = {
})),
};
-export default injectIntl(AuthnCustomValidationFormGroup);
+export default AuthnCustomValidationFormGroup;
diff --git a/src/common-components/tests/AuthnValidationFormGroup.test.jsx b/src/common-components/tests/AuthnValidationFormGroup.test.jsx
new file mode 100644
index 00000000..88f3dfbf
--- /dev/null
+++ b/src/common-components/tests/AuthnValidationFormGroup.test.jsx
@@ -0,0 +1,46 @@
+import React from 'react';
+import { mount } from 'enzyme';
+
+import AuthnCustomValidationFormGroup from '../AuthnValidationFormGroup';
+
+describe('AuthnCustomValidationFormGroup', () => {
+ let props = {
+ label: 'Email Label',
+ for: 'email',
+ name: 'email',
+ type: 'email',
+ value: '',
+ helpText: 'Email field help text',
+ };
+
+ it('should show label in place of placeholder when field is empty', () => {
+ const validationFormGroup = mount( );
+ expect(validationFormGroup.find('label').prop('className')).toEqual('pt-10 focus-out form-label');
+ });
+
+ it('should show label on top of field when field is focused in', () => {
+ const validationFormGroup = mount( );
+
+ validationFormGroup.find('input').simulate('focus');
+ expect(validationFormGroup.find('label').prop('className')).toEqual('pt-10 h6 form-label');
+ });
+
+ it('should keep label hidden for checkbox field', () => {
+ props = {
+ ...props,
+ type: 'checkbox',
+ optionalFieldCheckbox: true,
+ };
+ const validationFormGroup = mount( );
+ expect(validationFormGroup.find('label').prop('className')).toEqual('sr-only form-label');
+ });
+
+ it('should keep label hidden when input field is not empty', () => {
+ props = {
+ ...props,
+ value: 'test',
+ };
+ const validationFormGroup = mount( );
+ expect(validationFormGroup.find('label').prop('className')).toEqual('sr-only form-label');
+ });
+});
diff --git a/src/forgot-password/tests/__snapshots__/ForgotPasswordPage.test.jsx.snap b/src/forgot-password/tests/__snapshots__/ForgotPasswordPage.test.jsx.snap
index 4f05be99..5a886582 100644
--- a/src/forgot-password/tests/__snapshots__/ForgotPasswordPage.test.jsx.snap
+++ b/src/forgot-password/tests/__snapshots__/ForgotPasswordPage.test.jsx.snap
@@ -23,7 +23,12 @@ exports[`ForgotPasswordPage should match default section snapshot 1`] = `
-
+
+ Email
+
-
+
+ Email
+
-
+
+ Email
+
-
+
+ Email
+
-
+
+ Password
+
-
+
+ Email
+
-
+
+ Password
+
-
+
+ Email
+
-
+
+ Password
+
-
+
+ Email
+
-
+
+ Password
+
-
+
+ Email
+
-
+
+ Password
+
{getConfig().REGISTRATION_OPTIONAL_FIELDS ? (
{
expect(registrationPage.find('#validation-errors').first().text()).toEqual(alertBanner);
});
- it('should show error message on alert and below the fields incase of 409', () => {
+ it('should show error message on alert and below the fields in case of 409', () => {
const errors = {
email: 'It looks like test@gmail.com belongs to an existing account. Try again with a different email address.',
username: 'It looks like test belongs to an existing account. Try again with a different username.',
@@ -338,7 +338,7 @@ describe('RegistrationPageTests', () => {
expect(store.dispatch).toHaveBeenCalledWith(registerNewUser(formPayload));
});
- it('should display validationAlertMessages incase of invalid form submission', () => {
+ it('should display validationAlertMessages in case of invalid form submission', () => {
const alertMessages = {
name: [{ user_message: 'Please enter your full name.' }],
username: [{ user_message: 'Please enter your public username.' }],
diff --git a/src/register/tests/__snapshots__/RegistrationPage.test.jsx.snap b/src/register/tests/__snapshots__/RegistrationPage.test.jsx.snap
index 68fe577d..64f5e49e 100644
--- a/src/register/tests/__snapshots__/RegistrationPage.test.jsx.snap
+++ b/src/register/tests/__snapshots__/RegistrationPage.test.jsx.snap
@@ -35,7 +35,12 @@ exports[`RegistrationPageTests should match TPA provider snapshot 1`] = `