-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathModal.tsx
More file actions
121 lines (111 loc) · 3.63 KB
/
Copy pathModal.tsx
File metadata and controls
121 lines (111 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { forwardRef, useContext } from 'react';
import usePortal from 'react-cool-portal';
import styled from 'styled-components';
import cls from 'classnames';
import { ModalProps } from './Modal.types';
import { ModalSizes } from './Modal.enums';
import { useLockBodyScroll } from '../../hooks/useLockBodyScroll';
import { useOuterClick } from '../../hooks/useOuterCallback';
import { Inline, Padbox, Surface } from '../layout';
import { H4 } from '../Heading';
import { Overlay } from '../_internal/BaseOverlay';
import { pxToRem } from '../../utils';
import { mergeRefs } from '../../utils/mergeRefs';
import { SpaceSizes } from '../../theme';
import { DSContext } from '../../theme/DSProvider/DSProvider';
import { CloseButton } from '../CloseButton';
import { StretchEnum } from '../layout/Inline/Inline.enums';
import { CLX_COMPONENT } from '../../theme/constants';
import { FloatingProvider } from '../../contexts/FloatingContext';
import FocusTrap from '../FocusTrap';
const widthVariants = {
[ModalSizes.xs]: 320,
[ModalSizes.sm]: 430,
[ModalSizes.md]: 600,
[ModalSizes.lg]: 900,
[ModalSizes.xl]: 1440,
};
const BaseModal = styled(Surface)<{ $maxWidth: number }>`
display: flex;
flex-direction: column;
max-height: 90vh;
width: 90%;
max-width: ${({ $maxWidth }) => pxToRem($maxWidth)};
`;
const Title = styled(H4)`
margin: 0;
`;
const Header = styled.div`
padding: var(--sscds-space-dialog-content-padding);
padding-block-end: var(--sscds-space-2x);
`;
const Content = styled.div`
padding: var(--sscds-space-dialog-content-padding);
padding-block-start: 0;
overflow-y: auto;
`;
const Footer = styled(Padbox)`
border-top: 1px solid var(--sscds-border-color);
padding-inline: var(--sscds-space-dialog-content-padding);
padding-block: var(--sscds-space-4x);
`;
const Modal = forwardRef<HTMLDivElement, ModalProps>(
(
{
title,
onClose,
footer,
size = ModalSizes.md,
children,
className,
...rest
}: ModalProps,
ref,
) => {
const { portalsContainerId } = useContext(DSContext);
const { Portal } = usePortal({
containerId: portalsContainerId,
internalShowHide: false,
autoRemoveContainer: false,
});
const modalRef = useOuterClick<HTMLDivElement>(onClose);
useLockBodyScroll();
return (
<FloatingProvider>
<Portal>
<FocusTrap isActive>
<Overlay data-testid="dialog-overlay" placement="center">
<BaseModal
ref={mergeRefs<HTMLDivElement>(modalRef, ref)}
$maxWidth={widthVariants[size]}
className={cls(CLX_COMPONENT, className, 'ssc-ui-styled')}
elevation={3}
radius="lg"
hasBorder
{...rest}
>
<Inline stretch={StretchEnum.start}>
<Header className="sscds-modal-header">
{typeof title !== 'undefined' && <Title>{title}</Title>}
</Header>
{onClose && (
<CloseButton
marginCompensation={SpaceSizes.none}
style={{ position: 'relative', zIndex: 1 }}
onClose={onClose}
/>
)}
</Inline>
<Content className="sscds-modal-content">{children}</Content>
{typeof footer !== 'undefined' && (
<Footer className="sscds-modal-footer">{footer}</Footer>
)}
</BaseModal>
</Overlay>
</FocusTrap>
</Portal>
</FloatingProvider>
);
},
);
export default Modal;