Skip to content

Commit

Permalink
Convert Modal and BaseModal to TypeScript (#2355)
Browse files Browse the repository at this point in the history
* Convert Modal to tsx

* Migrate basemodal

* organize imports

* remove unused prop

* Setup userevent

* update url
  • Loading branch information
rohitvinnakota-codecov authored Nov 8, 2023
1 parent e356d61 commit 38a6095
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 103 deletions.
19 changes: 19 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
"@types/node": "^20.5.7",
"@types/react": "^18.2.7",
"@types/react-dom": "^18.2.4",
"@types/react-modal": "^3.16.2",
"@types/react-router-dom": "^5.3.3",
"autoprefixer": "^10.4.14",
"eslint": "^8.39.0",
Expand Down
24 changes: 12 additions & 12 deletions src/ui/Modal/BaseModal.jsx → src/ui/Modal/BaseModal.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import PropTypes from 'prop-types'
import React, { ReactElement } from 'react'

import Icon from 'ui/Icon'

function BaseModal({
interface BaseModalProps {
hasCloseButton?: boolean
onClose: () => void
title: ReactElement | string
subtitle?: ReactElement | string
body: ReactElement | string
footer?: ReactElement
}

const BaseModal: React.FC<BaseModalProps> = ({
onClose,
body,
footer,
title,
subtitle,
hasCloseButton = true,
}) {
}) => {
return (
<div className="rounded bg-white">
<header className="flex items-center justify-between px-4 pt-4">
Expand Down Expand Up @@ -39,13 +48,4 @@ function BaseModal({
)
}

BaseModal.propTypes = {
hasCloseButton: PropTypes.bool,
onClose: PropTypes.func.isRequired,
title: PropTypes.oneOfType([PropTypes.element, PropTypes.string]).isRequired,
subtitle: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),
body: PropTypes.oneOfType([PropTypes.element, PropTypes.string]).isRequired,
footer: PropTypes.element,
}

export default BaseModal
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ describe('Modal', () => {
title="modal title"
/>
)

await user.click(screen.getByLabelText('Close'))
expect(onClose).toHaveBeenCalled()
})
Expand Down
76 changes: 0 additions & 76 deletions src/ui/Modal/Modal.stories.jsx

This file was deleted.

98 changes: 98 additions & 0 deletions src/ui/Modal/Modal.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { Meta, StoryObj } from '@storybook/react'
import noop from 'lodash/noop'
import { useState } from 'react'

import Button from 'ui/Button'

import BaseModal from './BaseModal'
import Modal, { ModalProps } from './Modal'


export default {
title: 'Components/Modal',
component: Modal,
} as Meta

type Story = StoryObj<typeof Modal>

const RenderTemplate: React.FC<{ args: ModalProps }> = ({ args }) => {
const [isOpen, setIsOpen] = useState(false)
args.isOpen = isOpen
args.onClose = () => setIsOpen(false)
return (
<>
<Button
hook="open"
onClick={() => setIsOpen(true)}
to=""
disabled={false}
>
Open
</Button>
<Modal {...args} />
</>
)
}

export const SimpleModal: Story = {
args: {
title: 'Simple modal',
body: 'You can use the body to render any JSX',
},
render: (args) => <RenderTemplate args={args} />,
}

export const ModalWithFooter: Story = {
args: {
title: 'Modal with a footer',
body: 'The footer will appear under a line, good place for buttons',
footer: (
<Button to="" disabled={false} hook="">
Footer here
</Button>
),
},
render: (args) => <RenderTemplate args={args} />,
}

export const ModalWithSubtitle: Story = {
args: {
title: 'Modal with a subtitle',
subtitle: 'You can add some extra content under the title with this prop',
body: 'And it should render well with a body',
},
render: (args) => <RenderTemplate args={args} />,
}

export const ModalWithNoCloseButton: Story = {
args: {
title: 'Modal with no close button',
body: "You pass the prop hasCloseButton={false} so the close button doesn't appear next to the title",
hasCloseButton: false,
},
render: (args) => <RenderTemplate args={args} />,
}

export const BaseModalOnly: React.FC = () => (
<div className="bg-gray-900 p-20">
<div className="w-1/3">
<BaseModal
onClose={noop}
title="<BaseModal/>"
body={
<div className="flex flex-col">
<span>
You can only use the Modal/BaseModal to only use the styling of
the modal itself if you need to shell it differently
</span>
</div>
}
footer={
<Button to="" disabled={false} hook="">
Footer here
</Button>
}
/>
</div>
</div>
)
29 changes: 15 additions & 14 deletions src/ui/Modal/Modal.jsx → src/ui/Modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import PropTypes from 'prop-types'
import React, { ReactElement } from 'react'
import ReactModal from 'react-modal'

import BaseModal from './BaseModal'
Expand All @@ -8,7 +8,18 @@ const modalSizes = Object.freeze({
small: 'w-3/4 md:w-2/4 xl:w-2/4 2xl:w-1/4',
})

function Modal({
export interface ModalProps {
isOpen: boolean
onClose: () => void
body: ReactElement | string
footer?: ReactElement
title: ReactElement | string
subtitle?: ReactElement | string
hasCloseButton?: boolean
size?: 'medium' | 'small'
}

const Modal: React.FC<ModalProps> = ({
isOpen,
onClose,
body,
Expand All @@ -18,8 +29,9 @@ function Modal({
hasCloseButton = true,
size = 'medium',
...rest
}) {
}) => {
if (!isOpen) return null

return (
<ReactModal
isOpen={isOpen}
Expand All @@ -42,15 +54,4 @@ function Modal({
)
}

Modal.propTypes = {
isOpen: PropTypes.bool.isRequired,
hasCloseButton: PropTypes.bool,
onClose: PropTypes.func.isRequired,
title: PropTypes.oneOfType([PropTypes.element, PropTypes.string]).isRequired,
subtitle: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),
body: PropTypes.oneOfType([PropTypes.element, PropTypes.string]).isRequired,
footer: PropTypes.element,
size: PropTypes.string,
}

export default Modal

0 comments on commit 38a6095

Please sign in to comment.