Moving close button for Privacy modal to Message
This allow any Message to have a configurable close button. It also makes the styling more robust
This commit is contained in:
parent
f9b34ebd94
commit
fcf9a354f4
@ -16,16 +16,9 @@ exports[`Header closing the Privacy Policy modal 1`] = `
|
|||||||
shouldFocusAfterRender={true}
|
shouldFocusAfterRender={true}
|
||||||
shouldReturnFocusAfterClose={true}
|
shouldReturnFocusAfterClose={true}
|
||||||
>
|
>
|
||||||
<LoadNamespace(PrivacyPolicy) />
|
<LoadNamespace(PrivacyPolicy)
|
||||||
<button
|
onClose={[Function]}
|
||||||
className="modalClose"
|
/>
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<XSquare
|
|
||||||
color="currentColor"
|
|
||||||
size="24"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<header
|
<header
|
||||||
className="header"
|
className="header"
|
||||||
@ -95,16 +88,9 @@ exports[`Header closing the Privacy Policy modal 2`] = `
|
|||||||
shouldFocusAfterRender={true}
|
shouldFocusAfterRender={true}
|
||||||
shouldReturnFocusAfterClose={true}
|
shouldReturnFocusAfterClose={true}
|
||||||
>
|
>
|
||||||
<LoadNamespace(PrivacyPolicy) />
|
<LoadNamespace(PrivacyPolicy)
|
||||||
<button
|
onClose={[Function]}
|
||||||
className="modalClose"
|
/>
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<XSquare
|
|
||||||
color="currentColor"
|
|
||||||
size="24"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<header
|
<header
|
||||||
className="header"
|
className="header"
|
||||||
@ -174,16 +160,9 @@ exports[`Header opening the Privacy Policy modal 1`] = `
|
|||||||
shouldFocusAfterRender={true}
|
shouldFocusAfterRender={true}
|
||||||
shouldReturnFocusAfterClose={true}
|
shouldReturnFocusAfterClose={true}
|
||||||
>
|
>
|
||||||
<LoadNamespace(PrivacyPolicy) />
|
<LoadNamespace(PrivacyPolicy)
|
||||||
<button
|
onClose={[Function]}
|
||||||
className="modalClose"
|
/>
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<XSquare
|
|
||||||
color="currentColor"
|
|
||||||
size="24"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<header
|
<header
|
||||||
className="header"
|
className="header"
|
||||||
@ -253,16 +232,9 @@ exports[`Header rendering 1`] = `
|
|||||||
shouldFocusAfterRender={true}
|
shouldFocusAfterRender={true}
|
||||||
shouldReturnFocusAfterClose={true}
|
shouldReturnFocusAfterClose={true}
|
||||||
>
|
>
|
||||||
<LoadNamespace(PrivacyPolicy) />
|
<LoadNamespace(PrivacyPolicy)
|
||||||
<button
|
onClose={[Function]}
|
||||||
className="modalClose"
|
/>
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<XSquare
|
|
||||||
color="currentColor"
|
|
||||||
size="24"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<header
|
<header
|
||||||
className="header"
|
className="header"
|
||||||
@ -332,16 +304,9 @@ exports[`Header rendering with no banner 1`] = `
|
|||||||
shouldFocusAfterRender={true}
|
shouldFocusAfterRender={true}
|
||||||
shouldReturnFocusAfterClose={true}
|
shouldReturnFocusAfterClose={true}
|
||||||
>
|
>
|
||||||
<LoadNamespace(PrivacyPolicy) />
|
<LoadNamespace(PrivacyPolicy)
|
||||||
<button
|
onClose={[Function]}
|
||||||
className="modalClose"
|
/>
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<XSquare
|
|
||||||
color="currentColor"
|
|
||||||
size="24"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<header
|
<header
|
||||||
className="header"
|
className="header"
|
||||||
|
@ -5,7 +5,6 @@ import { Link } from 'gatsby';
|
|||||||
import { withNamespaces, Trans } from 'react-i18next';
|
import { withNamespaces, Trans } from 'react-i18next';
|
||||||
|
|
||||||
import GitlabIcon from 'react-feather/dist/icons/gitlab';
|
import GitlabIcon from 'react-feather/dist/icons/gitlab';
|
||||||
import CloseIcon from 'react-feather/dist/icons/x-square';
|
|
||||||
|
|
||||||
import LocaleSwitcher from 'components/LocaleSwitcher';
|
import LocaleSwitcher from 'components/LocaleSwitcher';
|
||||||
import InstallPrompt from 'components/InstallPrompt';
|
import InstallPrompt from 'components/InstallPrompt';
|
||||||
@ -46,12 +45,7 @@ class Header extends React.PureComponent {
|
|||||||
<Modal
|
<Modal
|
||||||
isOpen={ showModal }
|
isOpen={ showModal }
|
||||||
onRequestClose={ this.handleClose }>
|
onRequestClose={ this.handleClose }>
|
||||||
<PrivacyPolicy />
|
<PrivacyPolicy onClose={ this.handleClose } />
|
||||||
<button
|
|
||||||
className={ style.modalClose }
|
|
||||||
onClick={ this.handleClose }>
|
|
||||||
<CloseIcon />
|
|
||||||
</button>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<header
|
<header
|
||||||
className={ style.header }
|
className={ style.header }
|
||||||
|
@ -66,27 +66,3 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalClose {
|
|
||||||
position: absolute;
|
|
||||||
top: 3rem;
|
|
||||||
right: 2rem;
|
|
||||||
line-height: 2.8rem;
|
|
||||||
padding: 1rem;
|
|
||||||
margin: 0;
|
|
||||||
border: 0 none;
|
|
||||||
background: transparent;
|
|
||||||
color: inherit;
|
|
||||||
|
|
||||||
&:hover svg,
|
|
||||||
&:active svg {
|
|
||||||
color: var(--color-white);
|
|
||||||
}
|
|
||||||
|
|
||||||
& svg {
|
|
||||||
display: inline-block;
|
|
||||||
width: 2.8rem;
|
|
||||||
height: 2.8rem;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -21,6 +21,36 @@ exports[`Message rendering 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`Message rendering with a close button 1`] = `
|
||||||
|
<div
|
||||||
|
className="message"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="header"
|
||||||
|
>
|
||||||
|
<h2>
|
||||||
|
Testing
|
||||||
|
</h2>
|
||||||
|
<button
|
||||||
|
onClick={[MockFunction]}
|
||||||
|
>
|
||||||
|
<XSquare
|
||||||
|
color="currentColor"
|
||||||
|
size="24"
|
||||||
|
/>
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="content"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
Message content
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`Message rendering with icon 1`] = `
|
exports[`Message rendering with icon 1`] = `
|
||||||
<div
|
<div
|
||||||
className="message"
|
className="message"
|
||||||
|
@ -6,6 +6,7 @@ import style from './style.module.css';
|
|||||||
import InfoIcon from 'react-feather/dist/icons/info';
|
import InfoIcon from 'react-feather/dist/icons/info';
|
||||||
import ErrorIcon from 'react-feather/dist/icons/alert-octagon';
|
import ErrorIcon from 'react-feather/dist/icons/alert-octagon';
|
||||||
import WarningIcon from 'react-feather/dist/icons/alert-triangle';
|
import WarningIcon from 'react-feather/dist/icons/alert-triangle';
|
||||||
|
import CloseIcon from 'react-feather/dist/icons/x-square';
|
||||||
|
|
||||||
const iconTypes = {
|
const iconTypes = {
|
||||||
info: InfoIcon,
|
info: InfoIcon,
|
||||||
@ -23,7 +24,7 @@ const renderIcon = (type, icon) => {
|
|||||||
return <Icon />;
|
return <Icon />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Message = ({ type, icon, heading, children }) => (
|
const Message = ({ type, icon, heading, onClose, children }) => (
|
||||||
<div className={ [
|
<div className={ [
|
||||||
style.message,
|
style.message,
|
||||||
type && style[type]
|
type && style[type]
|
||||||
@ -31,6 +32,9 @@ const Message = ({ type, icon, heading, children }) => (
|
|||||||
<div className={ style.header }>
|
<div className={ style.header }>
|
||||||
{ renderIcon(type, icon) }
|
{ renderIcon(type, icon) }
|
||||||
<h2>{ heading }</h2>
|
<h2>{ heading }</h2>
|
||||||
|
{ onClose && <button onClick={ onClose }>
|
||||||
|
<CloseIcon /> Close
|
||||||
|
</button> }
|
||||||
</div>
|
</div>
|
||||||
<div className={ style.content }>
|
<div className={ style.content }>
|
||||||
{ children }
|
{ children }
|
||||||
@ -49,6 +53,7 @@ Message.propTypes = {
|
|||||||
PropTypes.func
|
PropTypes.func
|
||||||
]),
|
]),
|
||||||
heading: PropTypes.string.isRequired,
|
heading: PropTypes.string.isRequired,
|
||||||
|
onClose: PropTypes.func,
|
||||||
children: PropTypes.oneOfType([
|
children: PropTypes.oneOfType([
|
||||||
PropTypes.arrayOf(PropTypes.node),
|
PropTypes.arrayOf(PropTypes.node),
|
||||||
PropTypes.node
|
PropTypes.node
|
||||||
|
@ -24,6 +24,22 @@
|
|||||||
width: 2.8rem;
|
width: 2.8rem;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& button {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border: 0 none;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--color-tan);
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
font-size: 0;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
color: var(--color-white);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
@ -56,7 +72,7 @@
|
|||||||
& .header {
|
& .header {
|
||||||
background: var(--color-orange);
|
background: var(--color-orange);
|
||||||
|
|
||||||
& svg {
|
& > svg {
|
||||||
background: var(--color-black);
|
background: var(--color-black);
|
||||||
color: var(--color-orange);
|
color: var(--color-orange);
|
||||||
}
|
}
|
||||||
@ -68,7 +84,7 @@
|
|||||||
background: var(--color-blue);
|
background: var(--color-blue);
|
||||||
color: var(--color-white);
|
color: var(--color-white);
|
||||||
|
|
||||||
& svg {
|
& > svg {
|
||||||
background: var(--color-white);
|
background: var(--color-white);
|
||||||
color: var(--color-blue);
|
color: var(--color-blue);
|
||||||
}
|
}
|
||||||
|
@ -31,4 +31,13 @@ describe('Message', () => {
|
|||||||
);
|
);
|
||||||
expect(component).toMatchSnapshot();
|
expect(component).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('rendering with a close button', () => {
|
||||||
|
const component = shallow(
|
||||||
|
<Message heading="Testing" onClose={ jest.fn() }>
|
||||||
|
<p>Message content</p>
|
||||||
|
</Message>
|
||||||
|
);
|
||||||
|
expect(component).toMatchSnapshot();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
exports[`PrivacyPolicy rendering 1`] = `
|
exports[`PrivacyPolicy rendering 1`] = `
|
||||||
<Message
|
<Message
|
||||||
heading="TRANSLATE(Privacy Policy)"
|
heading="TRANSLATE(Privacy Policy)"
|
||||||
|
onClose={[MockFunction]}
|
||||||
type="info"
|
type="info"
|
||||||
>
|
>
|
||||||
<WithMergedOptions(TransComponent)
|
<WithMergedOptions(TransComponent)
|
||||||
|
@ -4,8 +4,8 @@ import { withNamespaces, Trans } from 'react-i18next';
|
|||||||
|
|
||||||
import Message from 'components/Message';
|
import Message from 'components/Message';
|
||||||
|
|
||||||
export const PrivacyPolicy = ({ t }) => (
|
export const PrivacyPolicy = ({ t, ...props }) => (
|
||||||
<Message type="info" heading={ t('Privacy Policy') }>
|
<Message type="info" heading={ t('Privacy Policy') } { ...props }>
|
||||||
<Trans i18nKey="Privacy policy copy">
|
<Trans i18nKey="Privacy policy copy">
|
||||||
<p>
|
<p>
|
||||||
Regexper and the tools used to create it are all open source. If you are
|
Regexper and the tools used to create it are all open source. If you are
|
||||||
|
@ -7,7 +7,7 @@ import { PrivacyPolicy } from 'components/PrivacyPolicy';
|
|||||||
describe('PrivacyPolicy', () => {
|
describe('PrivacyPolicy', () => {
|
||||||
test('rendering', () => {
|
test('rendering', () => {
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
<PrivacyPolicy t={ mockT } />
|
<PrivacyPolicy onClose={ jest.fn() } t={ mockT } />
|
||||||
);
|
);
|
||||||
expect(component).toMatchSnapshot();
|
expect(component).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user