diff --git a/gatsby-browser.js b/gatsby-browser.js index 05aba14..662ad55 100644 --- a/gatsby-browser.js +++ b/gatsby-browser.js @@ -1,4 +1,5 @@ import React from 'react'; +import Modal from 'react-modal'; import * as Sentry from '@sentry/browser'; import { I18nextProvider } from 'react-i18next'; @@ -7,6 +8,25 @@ import Layout from 'components/Layout'; import 'site.css'; +Modal.setAppElement('#___gatsby'); + +Modal.defaultStyles.overlay = { + ...Modal.defaultStyles.overlay, + backgroundColor: 'rgba(0, 0, 0, 0.25)' +}; +Modal.defaultStyles.content = { + ...Modal.defaultStyles.content, + background: 'transparent', + border: '0 solid', + borderRadius: '0', + overflow: null, + padding: '2rem', + top: '7rem', + bottom: '7rem', + left: '2rem', + right: '2rem' +}; + export const onClientEntry = () => { Sentry.getCurrentHub().getClient().getOptions().enabled = (navigator.doNotTrack !== '1' && window.doNotTrack !== '1'); diff --git a/package.json b/package.json index 8bc800f..dcd763b 100644 --- a/package.json +++ b/package.json @@ -108,6 +108,7 @@ "react-dom": "^16.7.0", "react-feather": "^1.1.5", "react-helmet": "^5.2.0", - "react-i18next": "^9.0.2" + "react-i18next": "^9.0.2", + "react-modal": "^3.8.1" } } diff --git a/src/components/Header/__snapshots__/test.js.snap b/src/components/Header/__snapshots__/test.js.snap index 36cf455..19f49f5 100644 --- a/src/components/Header/__snapshots__/test.js.snap +++ b/src/components/Header/__snapshots__/test.js.snap @@ -1,103 +1,401 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Header rendering 1`] = ` -
-

- - Regexper - -

- -
+ + + +
+

+ + Regexper + +

+ +
+ +`; + +exports[`Header closing the Privacy Policy modal 2`] = ` + + + + + + + +
+

+ + Regexper + +

+ +
+
+`; + +exports[`Header opening the Privacy Policy modal 1`] = ` + + + + + + + +
+

+ + Regexper + +

+ +
+
+`; + +exports[`Header rendering 1`] = ` + + + + + + + +
+

+ + Regexper + +

+ +
+
`; exports[`Header rendering with no banner 1`] = ` -
-

- - Regexper - -

- -
+ + + +
+

+ + Regexper + +

+ +
+ `; diff --git a/src/components/Header/index.js b/src/components/Header/index.js index 10c7558..f6d2a4a 100644 --- a/src/components/Header/index.js +++ b/src/components/Header/index.js @@ -1,52 +1,89 @@ import React from 'react'; import PropTypes from 'prop-types'; +import Modal from 'react-modal'; import { Link } from 'gatsby'; import { withNamespaces, Trans } from 'react-i18next'; import GitlabIcon from 'react-feather/dist/icons/gitlab'; +import CloseIcon from 'react-feather/dist/icons/x-square'; import LocaleSwitcher from 'components/LocaleSwitcher'; import InstallPrompt from 'components/InstallPrompt'; +import PrivacyPolicy from 'components/PrivacyPolicy'; import style from './style.module.css'; -export const Header = ({ banner }) => ( -
-

- Regexper -

+class Header extends React.PureComponent { + state = { + showModal: false + } - -
-); + +
+

+ Regexper +

-Header.propTypes = { - banner: PropTypes.oneOfType([ - PropTypes.bool, - PropTypes.string - ]).isRequired -}; + +
+ ; + } +} +export { Header }; export default withNamespaces()(Header); diff --git a/src/components/Header/style.module.css b/src/components/Header/style.module.css index 85f9272..1ebbd8f 100644 --- a/src/components/Header/style.module.css +++ b/src/components/Header/style.module.css @@ -66,3 +66,23 @@ } } } + +.modalClose { + position: absolute; + top: 3rem; + right: 2rem; + line-height: 2.8rem; + padding: 1rem; + + &:hover svg, + &:active svg { + color: var(--color-white); + } + + & svg { + display: inline-block; + width: 2.8rem; + height: 2.8rem; + vertical-align: middle; + } +} diff --git a/src/components/Header/test.js b/src/components/Header/test.js index 7d64c25..75cac6a 100644 --- a/src/components/Header/test.js +++ b/src/components/Header/test.js @@ -17,4 +17,32 @@ describe('Header', () => { ); expect(component).toMatchSnapshot(); }); + + test('opening the Privacy Policy modal', () => { + const component = shallow( +
+ ); + const eventObj = { preventDefault: jest.fn() }; + + component.instance().handleOpen(eventObj); + + expect(eventObj.preventDefault).toHaveBeenCalled(); + expect(component).toMatchSnapshot(); + }); + + test('closing the Privacy Policy modal', () => { + const component = shallow( +
+ ); + const eventObj = { preventDefault: jest.fn() }; + + component.setState({ showModal: true }); + + expect(component).toMatchSnapshot(); + + component.instance().handleClose(eventObj); + + expect(eventObj.preventDefault).toHaveBeenCalled(); + expect(component).toMatchSnapshot(); + }); }); diff --git a/src/components/Message/style.module.css b/src/components/Message/style.module.css index 4dd4b16..73bc5a5 100644 --- a/src/components/Message/style.module.css +++ b/src/components/Message/style.module.css @@ -5,6 +5,9 @@ color: var(--color-black); margin: var(--spacing-margin) 0; box-shadow: 0 0 1rem color(var(--color-black) alpha(0.7)); + max-height: 100%; + display: flex; + flex-direction: column; } .header { @@ -25,6 +28,7 @@ .content { padding: var(--spacing-margin); + overflow: auto; & p { margin-top: 0; diff --git a/yarn.lock b/yarn.lock index 33fc5d8..9513a3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4810,7 +4810,7 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -exenv@^1.2.1: +exenv@^1.2.0, exenv@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50= @@ -10542,7 +10542,7 @@ prompts@^0.1.9: kleur "^2.0.1" sisteransi "^0.1.1" -prop-types@^15.5.4, prop-types@^15.6.1, prop-types@^15.6.2: +prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.6.1, prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ== @@ -10834,11 +10834,21 @@ react-is@^16.3.2, react-is@^16.6.1, react-is@^16.7.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.7.0.tgz#c1bd21c64f1f1364c6f70695ec02d69392f41bfa" integrity sha512-Z0VRQdF4NPDoI0tsXVMLkJLiwEBa+RP66g0xDHxgxysxSoCUccSten4RTF/UFvZF1dZvZ9Zu1sx+MDXwcOR34g== -react-lifecycles-compat@^3.0.4: +react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-modal@^3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.8.1.tgz#7300f94a6f92a2e17994de0be6ccb61734464c9e" + integrity sha512-aLKeZM9pgXpIKVwopRHMuvqKWiBajkqisDA8UzocdCF6S4fyKVfLWmZR5G1Q0ODBxxxxf2XIwiCP8G/11GJAuw== + dependencies: + exenv "^1.2.0" + prop-types "^15.5.10" + react-lifecycles-compat "^3.0.0" + warning "^3.0.0" + react-side-effect@^1.1.0: version "1.1.5" resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.1.5.tgz#f26059e50ed9c626d91d661b9f3c8bb38cd0ff2d"