Skip to content

Commit

Permalink
Consistently track modal events (#1007)
Browse files Browse the repository at this point in the history
* Add headline to Modal stories

* Split modal code

* Consistently track modal events

* Test the modal context functions

* Add changeset
  • Loading branch information
connor-baer authored Jun 28, 2021
1 parent 8f181a6 commit efe0210
Show file tree
Hide file tree
Showing 9 changed files with 421 additions and 320 deletions.
5 changes: 5 additions & 0 deletions .changeset/blue-hounds-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sumup/circuit-ui': patch
---

Refactored the modal components to consistently dispatch tracking events.
19 changes: 17 additions & 2 deletions packages/circuit-ui/components/Modal/Modal.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Theme } from '@sumup/design-tokens';

import { Stack } from '../../../../.storybook/components';
import Button from '../Button';
import Headline from '../Headline';
import Body from '../Body';
import Image from '../Image';
import { ModalProvider } from '../ModalContext';
Expand Down Expand Up @@ -56,7 +57,11 @@ export const Base = (modal: ModalProps): JSX.Element => {
};

Base.args = {
children: 'Hello World!',
children: (
<Headline as="h2" size="three">
Hello World!
</Headline>
),
variant: 'contextual',
closeButtonLabel: 'Close modal',
};
Expand All @@ -82,7 +87,11 @@ export const Variants = (modal: ModalProps): JSX.Element => {
};

Variants.args = {
children: 'Hello World!',
children: (
<Headline as="h2" size="three">
Hello World!
</Headline>
),
closeButtonLabel: 'Close modal',
};

Expand All @@ -106,6 +115,9 @@ export const PreventClose = (modal: ModalProps): JSX.Element => {
PreventClose.args = {
children: ({ onClose }: { onClose: ModalProps['onClose'] }) => (
<Fragment>
<Headline as="h2" size="three">
Complete the action
</Headline>
<Body>
Users have to complete the action inside the modal to close it. The
close button is hidden and clicking outside the modal or pressing the
Expand Down Expand Up @@ -166,6 +178,9 @@ CustomStyles.args = {
children: (
<Fragment>
<Image src="https://source.unsplash.com/TpHmEoVSmfQ/1600x900" alt="" />
<Headline as="h2" size="three">
Custom styles
</Headline>
<Body css={spacing('mega')}>
Custom styles can be applied using the <code>css</code> prop.
</Body>
Expand Down
249 changes: 121 additions & 128 deletions packages/circuit-ui/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ import ReactModal from 'react-modal';
import { Theme } from '@sumup/design-tokens';

import { isFunction } from '../../util/type-check';
import { useClickHandler } from '../../hooks/useClickHandler';
import { ModalComponent, BaseModalProps } from '../ModalContext/ModalContext';
import { ModalComponent, BaseModalProps } from '../ModalContext';
import CloseButton from '../CloseButton';

const TRANSITION_DURATION_MOBILE = 120;
Expand Down Expand Up @@ -91,146 +90,140 @@ export const Modal: ModalComponent<ModalProps> = ({
variant,
preventClose = false,
closeButtonLabel,
tracking = {},
className,
...props
}) => {
const handleClose = useClickHandler(onClose, tracking, 'modal-close');
return (
<ClassNames<Theme> key={variant}>
{({ css: cssString, cx, theme }) => {
// React Modal styles
// https://reactcommunity.org/react-modal/styles/classes/

const styles = {
base: cx(
cssString`
position: fixed;
outline: none;
background-color: ${theme.colors.white};
}) => (
<ClassNames<Theme> key={variant}>
{({ css: cssString, cx, theme }) => {
// React Modal styles
// https://reactcommunity.org/react-modal/styles/classes/

const styles = {
base: cx(
cssString`
position: fixed;
outline: none;
background-color: ${theme.colors.white};
${theme.mq.untilKilo} {
right: 0;
bottom: 0;
left: 0;
-webkit-overflow-scrolling: touch;
overflow-y: auto;
width: 100vw;
transform: translateY(100%);
transition: transform ${TRANSITION_DURATION_MOBILE}ms ease-in-out;
padding: ${theme.spacings.mega};
}
${theme.mq.untilKilo} {
right: 0;
bottom: 0;
left: 0;
-webkit-overflow-scrolling: touch;
overflow-y: auto;
width: 100vw;
transform: translateY(100%);
transition: transform ${TRANSITION_DURATION_MOBILE}ms ease-in-out;
padding: ${theme.spacings.mega};
}
${theme.mq.kilo} {
top: 50%;
left: 50%;
padding: ${theme.spacings.giga};
transform: translate(-50%, -50%);
min-height: 320px;
max-height: 90vh;
min-width: 480px;
max-width: 90vw;
opacity: 0;
transition: opacity ${TRANSITION_DURATION_DESKTOP}ms ease-in-out;
border-radius: ${theme.borderRadius.mega};
}
`,
variant === 'immersive' &&
cssString`
${theme.mq.kilo} {
top: 50%;
left: 50%;
padding: ${theme.spacings.giga};
transform: translate(-50%, -50%);
min-height: 320px;
max-height: 90vh;
min-width: 480px;
max-width: 90vw;
opacity: 0;
transition: opacity ${TRANSITION_DURATION_DESKTOP}ms ease-in-out;
border-radius: ${theme.borderRadius.mega};
}
`,
variant === 'immersive' &&
cssString`
${theme.mq.untilKilo} {
height: 100vh;
}
`,
variant === 'contextual' &&
cssString`
variant === 'contextual' &&
cssString`
${theme.mq.untilKilo} {
max-height: calc(100vh - ${theme.spacings.mega});
border-top-left-radius: ${theme.borderRadius.mega};
border-top-right-radius: ${theme.borderRadius.mega};
}
`,
className,
),
// The !important below is necessary because of some weird
// style specificity issues in Emotion.
afterOpen: cssString`
label: modal--after-open;
${theme.mq.untilKilo} {
transform: translateY(0) !important;
}
${theme.mq.kilo} {
opacity: 1 !important;
}
`,
beforeClose: cssString`
label: modal--before-close;
${theme.mq.untilKilo} {
transform: translateY(100%);
}
${theme.mq.kilo} {
opacity: 0;
}
`,
};

const overlayStyles = {
base: cssString`
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
className,
),
// The !important below is necessary because of some weird
// style specificity issues in Emotion.
afterOpen: cssString`
label: modal--after-open;
${theme.mq.untilKilo} {
transform: translateY(0) !important;
}
${theme.mq.kilo} {
opacity: 1 !important;
}
`,
beforeClose: cssString`
label: modal--before-close;
${theme.mq.untilKilo} {
transform: translateY(100%);
}
${theme.mq.kilo} {
opacity: 0;
transition: opacity ${TRANSITION_DURATION_MOBILE}ms ease-in-out;
background: ${theme.colors.overlay};
z-index: ${theme.zIndex.modal};
${theme.mq.kilo} {
-webkit-overflow-scrolling: touch;
overflow-y: auto;
transition: opacity ${TRANSITION_DURATION_DESKTOP}ms ease-in-out;
}
`,
afterOpen: cssString`
opacity: 1;
`,
beforeClose: cssString`
opacity: 0;
`,
};

const reactModalProps = {
className: styles,
overlayClassName: overlayStyles,
onRequestClose: handleClose,
closeTimeoutMS: TRANSITION_DURATION,
shouldCloseOnOverlayClick: !preventClose,
shouldCloseOnEsc: !preventClose,
...props,
};

return (
<ReactModal {...reactModalProps}>
{!preventClose && closeButtonLabel && (
<CloseButton
onClick={onClose}
label={closeButtonLabel}
css={closeButtonStyles}
/>
)}

{isFunction(children)
? children({ onClose: handleClose })
: children}
</ReactModal>
);
}}
</ClassNames>
);
};
}
`,
};

const overlayStyles = {
base: cssString`
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
opacity: 0;
transition: opacity ${TRANSITION_DURATION_MOBILE}ms ease-in-out;
background: ${theme.colors.overlay};
z-index: ${theme.zIndex.modal};
${theme.mq.kilo} {
-webkit-overflow-scrolling: touch;
overflow-y: auto;
transition: opacity ${TRANSITION_DURATION_DESKTOP}ms ease-in-out;
}
`,
afterOpen: cssString`
opacity: 1;
`,
beforeClose: cssString`
opacity: 0;
`,
};

const reactModalProps = {
className: styles,
overlayClassName: overlayStyles,
onRequestClose: onClose,
closeTimeoutMS: TRANSITION_DURATION,
shouldCloseOnOverlayClick: !preventClose,
shouldCloseOnEsc: !preventClose,
...props,
};

return (
<ReactModal {...reactModalProps}>
{!preventClose && closeButtonLabel && (
<CloseButton
onClick={onClose}
label={closeButtonLabel}
css={closeButtonStyles}
/>
)}

{isFunction(children) ? children({ onClose }) : children}
</ReactModal>
);
}}
</ClassNames>
);

Modal.TIMEOUT = TRANSITION_DURATION;
Loading

0 comments on commit efe0210

Please sign in to comment.