Refactor/modal component tests 1332 (#1392)

* feat: Add separate constants in theme for modal sizes and paddings

* feat: Implement dynamic sizing and padding for Modal

* feat: use dynamic modal feature for csv import

* fix: Remove redundant props from spreadsheet-import

* fix: use theme.spacing() instead

* fix: place types to Modal.tsx, convert ternary to switch-case, give default value

* fix: give px to modal sizes

* enhance: add color style to modal

* feat: add modal to storybook
This commit is contained in:
Mustajab Ikram
2023-09-08 02:04:32 +05:30
committed by GitHub
parent a902b7c6fe
commit bd2e4307d2
5 changed files with 77 additions and 26 deletions

View File

@ -37,7 +37,7 @@ export const ModalWrapper = ({ children, isOpen, onClose }: Props) => {
const { rtl } = useSpreadsheetImportInternal();
return (
<StyledModal isOpen={isOpen}>
<StyledModal isOpen={isOpen} size="large">
<StyledRtlLtr dir={rtl ? 'rtl' : 'ltr'}>
<ModalCloseButton onClose={onClose} />
{children}

View File

@ -12,14 +12,46 @@ import {
import { ModalHotkeyScope } from './types/ModalHotkeyScope';
const StyledModalDiv = styled(motion.div)`
const StyledModalDiv = styled(motion.div)<{
size?: ModalSize;
padding?: ModalPadding;
}>`
display: flex;
flex-direction: column;
background: ${({ theme }) => theme.background.primary};
color: ${({ theme }) => theme.font.color.primary};
border-radius: ${({ theme }) => theme.border.radius.md};
overflow: hidden;
max-height: 90vh;
z-index: 10000; // should be higher than Backdrop's z-index
width: ${({ size, theme }) => {
switch (size) {
case 'small':
return theme.modal.size.sm;
case 'medium':
return theme.modal.size.md;
case 'large':
return theme.modal.size.lg;
default:
return 'auto';
}
}};
padding: ${({ padding, theme }) => {
switch (padding) {
case 'none':
return theme.spacing(0);
case 'small':
return theme.spacing(2);
case 'medium':
return theme.spacing(4);
case 'large':
return theme.spacing(6);
default:
return 'auto';
}
}};
`;
const StyledHeader = styled.div`
@ -85,12 +117,17 @@ function ModalFooter({ children, ...restProps }: ModalFooterProps) {
/**
* Modal
*/
export type ModalSize = 'small' | 'medium' | 'large';
export type ModalPadding = 'none' | 'small' | 'medium' | 'large';
type ModalProps = React.PropsWithChildren &
React.ComponentProps<'div'> & {
isOpen?: boolean;
onClose?: () => void;
hotkeyScope?: ModalHotkeyScope;
onEnter?: () => void;
size?: ModalSize;
padding?: ModalPadding;
};
const modalVariants = {
@ -105,6 +142,8 @@ export function Modal({
onClose,
hotkeyScope = ModalHotkeyScope.Default,
onEnter,
size = 'medium',
padding = 'medium',
...restProps
}: ModalProps) {
const modalRef = useRef<HTMLDivElement>(null);
@ -157,6 +196,8 @@ export function Modal({
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
ref={modalRef}
size={size}
padding={padding}
initial="hidden"
animate="visible"
exit="exit"

View File

@ -1,39 +1,40 @@
import styled from '@emotion/styled';
import { Meta, StoryObj } from '@storybook/react';
import type { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { Modal } from '../Modal';
import { ModalHotkeyScope } from '../types/ModalHotkeyScope';
const meta: Meta<typeof Modal> = {
title: 'UI/Modal/Modal',
component: Modal,
decorators: [ComponentDecorator],
};
export default meta;
export default meta;
type Story = StoryObj<typeof Modal>;
const StyledContentContainer = styled.div`
color: ${({ theme }) => theme.font.color.primary};
margin: 5px;
padding: ${({ theme }) => theme.spacing(10)};
`;
const args = {
isOpen: true,
children: (
<Modal.Content>
<StyledContentContainer>Lorem ipsum</StyledContentContainer>
</Modal.Content>
),
};
export const Default: Story = {
args,
args: {
isOpen: true,
size: 'medium',
padding: 'medium',
hotkeyScope: ModalHotkeyScope.Default,
children: (
<>
<Modal.Header>Stay in touch</Modal.Header>
<Modal.Content>
This is a dummy newletter form so don't bother trying to test it. Not
that I expect you to, anyways. :)
</Modal.Content>
<Modal.Footer>
By using Twenty, you're opting for the finest CRM experience you'll
ever encounter.
</Modal.Footer>
</>
),
},
decorators: [ComponentDecorator],
};
Default.argTypes = {
children: { control: false },
argTypes: {
children: { control: false },
},
};

View File

@ -0,0 +1,7 @@
export const modal = {
size: {
sm: '300px',
md: '400px',
lg: '53%',
},
};

View File

@ -7,6 +7,7 @@ import { boxShadowDark, boxShadowLight } from './boxShadow';
import { color, grayScale } from './colors';
import { fontDark, fontLight } from './font';
import { icon } from './icon';
import { modal } from './modal';
import { tagDark, tagLight } from './tag';
import { text } from './text';
@ -14,6 +15,7 @@ const common = {
color: color,
grayScale: grayScale,
icon: icon,
modal: modal,
text: text,
blur: blur,
animation: animation,