diff --git a/package-lock.json b/package-lock.json index b8be729c..1b7a4821 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3877,6 +3877,19 @@ "babel-polyfill": "6.26.0", "react-responsive": "8.0.3", "react-transition-group": "4.3.0" + }, + "dependencies": { + "react-responsive": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-8.0.3.tgz", + "integrity": "sha512-F9VXyLao7O8XHXbLjQbIr4+mC6Zr0RDTwNjd7ixTmYEAyKyNanBkLkFchNaMZgszoSK6PgSs/3m/QDWw33/gpg==", + "requires": { + "hyphenate-style-name": "^1.0.0", + "matchmediaquery": "^0.3.0", + "prop-types": "^15.6.1", + "shallow-equal": "^1.1.0" + } + } } }, "@edx/frontend-platform": { @@ -21058,9 +21071,9 @@ } }, "react-responsive": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-8.0.3.tgz", - "integrity": "sha512-F9VXyLao7O8XHXbLjQbIr4+mC6Zr0RDTwNjd7ixTmYEAyKyNanBkLkFchNaMZgszoSK6PgSs/3m/QDWw33/gpg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-8.2.0.tgz", + "integrity": "sha512-iagCqVrw4QSjhxKp3I/YK6+ODkWY6G+YPElvdYKiUUbywwh9Ds0M7r26Fj2/7dWFFbOpcGnJE6uE7aMck8j5Qg==", "requires": { "hyphenate-style-name": "^1.0.0", "matchmediaquery": "^0.3.0", diff --git a/package.json b/package.json index 2f84164d..963a4532 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "react-helmet": "6.1.0", "react-loading-skeleton": "2.2.0", "react-redux": "7.2.3", + "react-responsive": "8.2.0", "react-router": "5.2.0", "react-router-dom": "5.2.0", "redux": "4.0.5", diff --git a/src/_style.scss b/src/_style.scss index f907c0f7..1468872c 100644 --- a/src/_style.scss +++ b/src/_style.scss @@ -13,6 +13,7 @@ $microsoft-black: #2f2f2f; $microsoft-focus-black: #000; $apple-black: #000000; $apple-focus-black: $apple-black; +$accent-a-light: #c9f2f5; .sr-only { position: absolute; @@ -282,6 +283,10 @@ $apple-focus-black: $apple-black; margin-top: 10px; } +.mt-7 { + margin-top: 7rem; +} + .pt-10 { padding-top: 10px; } @@ -323,6 +328,92 @@ $apple-focus-black: $apple-black; } } -.custom-select-size { - background-size: 8px 10px; +.large-screen-container { + background-color: $white; + background-image: linear-gradient(102.02deg, $primary 45%, $white 45%); + width: 100%; +} + +.medium-screen-header { + background-color: $white; + background-image: linear-gradient(102.02deg, $primary 93%, $white 7%); + width: 100%; +} + +.large-screen-top-stripe { + height: 0.5rem; + background-image: linear-gradient( + 102.02deg, + $brand-700, + $brand-700 10%, + $brand 10%, + $brand 40%, + $primary-700 40%, + $primary-700 50%, + $accent-a 50%, + $accent-a 72%, + $accent-a-light 72%, + ); + background-repeat: no-repeat; +} + +.medium-screen-top-stripe { + height: 0.5rem; + background-image: linear-gradient( + 102.02deg, + $brand-700, + $brand-700 10%, + $brand 10%, + $brand 90%, + $primary-700 90%, + $primary-700 100%, + ); + background-repeat: no-repeat; +} + +.small-screen-top-stripe { + height: 0.5rem; + background-image: linear-gradient( + 102.02deg, + $brand-700, + $brand-700 20%, + $brand 20%, + ); + background-repeat: no-repeat; +} + +.svg-line { + padding-top: 0.5rem; + stroke: $accent-b; + stroke-width: 0.5rem; + width: 7em; +} + +.small-screen-svg-line { + padding-top: 0.5rem; + stroke: $accent-b; + stroke-width: 0.25rem; + width: 4em; + height: 72px; +} + +.large-heading { + padding-left: 1rem; + color: $white; + max-width: 24rem; + line-height: 78px; + font-size: 78px; +} + +.small-heading { + padding-left: 0.5rem; + color: $white; + line-height: 40px; + font-size: 36px; +} + +.logo { + width: 4.5rem; + padding-top: 2rem; + padding-left: 25px; } diff --git a/src/common-components/BaseComponent.jsx b/src/common-components/BaseComponent.jsx new file mode 100644 index 00000000..6fbde355 --- /dev/null +++ b/src/common-components/BaseComponent.jsx @@ -0,0 +1,34 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import Responsive from 'react-responsive'; + +import SmallScreenLayout from './SmallScreenLayout'; +import MediumScreenLayout from './MediumScreenLayout'; +import LargeScreenLayout from './LargeScreenLayout'; + +const BaseComponent = ({ children }) => ( + <> + + + {children} + + + + + {children} + + + + + {children} + + + +); + +BaseComponent.propTypes = { + children: PropTypes.node.isRequired, +}; + +export default BaseComponent; diff --git a/src/common-components/LargeScreenLayout.jsx b/src/common-components/LargeScreenLayout.jsx new file mode 100644 index 00000000..a26bb9de --- /dev/null +++ b/src/common-components/LargeScreenLayout.jsx @@ -0,0 +1,29 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import { Row } from '@edx/paragon'; + +import LargeScreenLeftLayout from './LargeScreenLeftLayout'; +import LargeScreenRightLayout from './LargeScreenRightLayout'; + +const LargeScreenLayout = (props) => { + const { children } = props; + + return ( + <> +
+ + + + { children } + + + + ); +}; + +LargeScreenLayout.propTypes = { + children: PropTypes.node.isRequired, +}; + +export default LargeScreenLayout; diff --git a/src/common-components/LargeScreenLeftLayout.jsx b/src/common-components/LargeScreenLeftLayout.jsx new file mode 100644 index 00000000..263a7803 --- /dev/null +++ b/src/common-components/LargeScreenLeftLayout.jsx @@ -0,0 +1,34 @@ +import React from 'react'; + +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +import { getConfig } from '@edx/frontend-platform'; +import { Col } from '@edx/paragon'; + +import messages from './messages'; + +const LargeScreenLeftLayout = (props) => { + const { intl } = props; + + return ( + + edx +
+ + + +

+ {intl.formatMessage(messages['start.learning'])} +
+ {intl.formatMessage(messages['with.site.name'], { siteName: getConfig().SITE_NAME })} +
+

+
+ + ); +}; + +LargeScreenLeftLayout.propTypes = { + intl: intlShape.isRequired, +}; + +export default injectIntl(LargeScreenLeftLayout); diff --git a/src/common-components/LargeScreenRightLayout.jsx b/src/common-components/LargeScreenRightLayout.jsx new file mode 100644 index 00000000..a682cdd5 --- /dev/null +++ b/src/common-components/LargeScreenRightLayout.jsx @@ -0,0 +1,20 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import { Col } from '@edx/paragon'; + +const LargeScreenRightLayout = (props) => { + const { children } = props; + + return ( + + { children } + + ); +}; + +LargeScreenRightLayout.propTypes = { + children: PropTypes.node.isRequired, +}; + +export default LargeScreenRightLayout; diff --git a/src/common-components/MediumScreenHeader.jsx b/src/common-components/MediumScreenHeader.jsx new file mode 100644 index 00000000..1fcbb849 --- /dev/null +++ b/src/common-components/MediumScreenHeader.jsx @@ -0,0 +1,36 @@ +import React from 'react'; + +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +import { getConfig } from '@edx/frontend-platform'; + +import messages from './messages'; + +const MediumScreenHeader = (props) => { + const { intl } = props; + + return ( + <> +
+
+ edx +
+ + + +

+ {intl.formatMessage(messages['start.learning'])} +
+ {intl.formatMessage(messages['with.site.name'], { siteName: getConfig().SITE_NAME })} +
+

+
+
+ + ); +}; + +MediumScreenHeader.propTypes = { + intl: intlShape.isRequired, +}; + +export default injectIntl(MediumScreenHeader); diff --git a/src/common-components/MediumScreenLayout.jsx b/src/common-components/MediumScreenLayout.jsx new file mode 100644 index 00000000..ab5fa1c5 --- /dev/null +++ b/src/common-components/MediumScreenLayout.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import MediumScreenHeader from './MediumScreenHeader'; + +const MediumScreenLayout = (props) => { + const { children } = props; + + return ( + <> + + { children } + + ); +}; + +MediumScreenLayout.propTypes = { + children: PropTypes.node.isRequired, +}; + +export default MediumScreenLayout; diff --git a/src/common-components/SmallScreenHeader.jsx b/src/common-components/SmallScreenHeader.jsx new file mode 100644 index 00000000..68c131c3 --- /dev/null +++ b/src/common-components/SmallScreenHeader.jsx @@ -0,0 +1,37 @@ +import React from 'react'; + +import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +import { getConfig } from '@edx/frontend-platform'; + +import messages from './messages'; + +const SmallScreenHeader = (props) => { + const { intl } = props; + + return ( + <> +
+
+ edx +
+ + + +

+ {intl.formatMessage(messages['start.learning'])} +
+ + {intl.formatMessage(messages['with.site.name'], { siteName: getConfig().SITE_NAME })} + +

+
+
+ + ); +}; + +SmallScreenHeader.propTypes = { + intl: intlShape.isRequired, +}; + +export default injectIntl(SmallScreenHeader); diff --git a/src/common-components/SmallScreenLayout.jsx b/src/common-components/SmallScreenLayout.jsx new file mode 100644 index 00000000..503cd4f8 --- /dev/null +++ b/src/common-components/SmallScreenLayout.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import SmallScreenHeader from './SmallScreenHeader'; + +const SmallScreenLayout = (props) => { + const { children } = props; + + return ( + <> + + { children } + + ); +}; + +SmallScreenLayout.propTypes = { + children: PropTypes.node.isRequired, +}; + +export default SmallScreenLayout; diff --git a/src/common-components/index.jsx b/src/common-components/index.jsx index 20894220..0b31641e 100644 --- a/src/common-components/index.jsx +++ b/src/common-components/index.jsx @@ -12,3 +12,4 @@ export { default as APIFailureMessage } from './APIFailureMessage'; export { default as reducer } from './data/reducers'; export { default as saga } from './data/sagas'; export { storeName } from './data/selectors'; +export { default as BaseComponent } from './BaseComponent'; diff --git a/src/common-components/messages.jsx b/src/common-components/messages.jsx index d667457d..ab1d6433 100644 --- a/src/common-components/messages.jsx +++ b/src/common-components/messages.jsx @@ -60,6 +60,16 @@ const messages = defineMessages({ defaultMessage: 'Create account using {providerName}', description: 'Screen reader text that appears before social auth provider name', }, + 'start.learning': { + id: 'start.learning', + defaultMessage: 'Start Learning', + description: 'Header text for logistration MFE pages', + }, + 'with.site.name': { + id: 'with.site.name', + defaultMessage: 'with {siteName}', + description: 'Header text with site name for logistration MFE pages', + }, }); export default messages; diff --git a/src/index.jsx b/src/index.jsx index 3c3e4f5d..faae7450 100755 --- a/src/index.jsx +++ b/src/index.jsx @@ -19,7 +19,7 @@ import { } from './data/constants'; import ForgotPasswordPage from './forgot-password'; import { - HeaderLayout, UnAuthOnlyRoute, registerIcons, NotFoundPage, + BaseComponent, UnAuthOnlyRoute, registerIcons, NotFoundPage, } from './common-components'; import ResetPasswordPage from './reset-password'; import WelcomePage from './welcome'; @@ -32,7 +32,7 @@ registerIcons(); subscribe(APP_READY, () => { ReactDOM.render( - + @@ -47,7 +47,7 @@ subscribe(APP_READY, () => { - + , document.getElementById('root'), );