Skip to content

Commit

Permalink
refactor: move modal components to separate files
Browse files Browse the repository at this point in the history
  • Loading branch information
vickonrails committed May 20, 2021
1 parent 509ca80 commit 7589537
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 70 deletions.
41 changes: 12 additions & 29 deletions example/src/App.tsx
Expand Up @@ -6,6 +6,7 @@ import {
Button,
ModalTitle,
ModalOverlay,
ModalContent,
Flex
} from 'avocado-ui'
import { ThemeProvider } from '@emotion/react'
Expand All @@ -29,35 +30,16 @@ const App = () => {
open={modalOpen}
onClose={() => <p>hey</p>}
initialFocus={initialBtnRef}
style={{
position: 'fixed',
zIndex: 10,
width: '100%'
}}
>
<ModalOverlay
style={{
background: 'rgba(0,0,0,.7)',
position: 'fixed',
top: 0,
bottom: 0,
display: 'flex',
left: 0,
right: 0,
zIndex: -1
}}
>
<div
style={{
background: 'white',
margin: '2em auto 0',
height: '200px',
width: '300px',
padding: '.6em',
borderRadius: '4px'
}}
>
<ModalTitle as='h2'>Children</ModalTitle>
<ModalOverlay>
<ModalContent>
<ModalTitle as='h5'>Children</ModalTitle>
<p>
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Quaerat
veritatis provident esse recusandae veniam harum tenetur, placeat
ea similique nemo et illo ut odit repellendus animi sapiente
architecto doloremque quidem.
</p>
<Flex gap={5} justifyContent='flex-start'>
<Button size='sm'>One Thing</Button>

Expand All @@ -66,11 +48,12 @@ const App = () => {
onClick={() => setMoalOpen(false)}
variant='error'
ref={initialBtnRef}
buttonType='ghost'
>
Close
</Button>
</Flex>
</div>
</ModalContent>
</ModalOverlay>
</Modal>
</ThemeProvider>
Expand Down
39 changes: 39 additions & 0 deletions src/components/modal/content.tsx
@@ -0,0 +1,39 @@
import React, { FC, ElementType, HTMLAttributes } from 'react'
import { Dialog } from '@headlessui/react'
import styled from '@emotion/styled'

const { Description } = Dialog

// Wraps around Modal Content
const ModalContent: FC<ModalContentProps> = ({
as,
className,
children,
...props
}) => {
const _className = className
? `avocado-modal__content ${className}`
: `avocado-modal__content`
return (
<StyledModalContent {...props} as={as || 'div'} className={_className}>
{children}
</StyledModalContent>
)
}

interface ModalContentProps extends HTMLAttributes<HTMLElement> {
/**
* as - specifies the html element the component should be rendered as
*/
as?: ElementType<any>
}

const StyledModalContent = styled<any>(Description)`
background: white;
margin: 2em auto 0;
max-width: 500px;
padding: 1em;
border-radius: 4px;
`

export { ModalContent }
3 changes: 3 additions & 0 deletions src/components/modal/index.ts
@@ -1 +1,4 @@
export * from './modal'
export * from './content'
export * from './title'
export * from './overlay'
79 changes: 38 additions & 41 deletions src/components/modal/modal.tsx
@@ -1,74 +1,71 @@
import React, { ElementType, FC, HTMLAttributes } from 'react'
import styled from '@emotion/styled'
import { Dialog } from '@headlessui/react'

/*
* Modal Component
*/

const Modal: FC<ModalProps> = ({
children,
open,
onClose,
// destroy,
initialFocus,
unmount,
className,
as,
...props
}) => {
const _className = className ? `avocado-modal ${className}` : `avocado-modal`

return (
<Dialog
<StyledModal
onClose={onClose}
// static={destroy}
unmount={unmount}
as={as}
as={as || 'div'}
initialFocus={initialFocus}
open={open}
{...props}
className={_className}
>
{children}
</Dialog>
</StyledModal>
)
}

type ModalProps = PrimitiveModalProps & HTMLAttributes<HTMLElement>

const StyledModal = styled<any>(Dialog)`
position: 'fixed',
zIndex: 10,
width: '100%'
`

interface PrimitiveModalProps {
/**
* open - sets the state of the Dialog. Whether the Dialog is open or not.
*/
open: boolean | undefined
onClose: (item: false) => void
destroy?: boolean
unmount?: boolean
as?: React.ElementType<any>
initialFocus?: React.MutableRefObject<any>
}

const ModalTitle: FC<ModalTitleProps> = ({ children, as, ...props }) => {
const { Title } = Dialog
return (
<Title as={as} {...props}>
{children}
</Title>
)
}

const ModalOverlay: FC<HTMLAttributes<HTMLElement>> = ({
children,
...props
}) => {
const { Overlay } = Dialog
return <Overlay {...props}>{children}</Overlay>
}
/**
* onClose - function to execute while closing the Dialog
*/
onClose: (item: false) => void

interface ModalTitleProps {
as: ElementType<any>
}
/**
* unmount - controls if the Dialog should be unmounted or hidden when closed
*/
unmount?: boolean

const ModalContent: FC<ModalContentProps> = ({ as, children, ...props }) => {
const { Description } = Dialog
return (
<Description {...props} as={as}>
{children}
</Description>
)
}
/**
* as - specifies the html element the component should be rendered as
*/
as?: ElementType<any>

interface ModalContentProps {
as: ElementType<any>
/**
* initialFocus - control the element that receives focus once the modal is open. Only elements in the tab order can be focused.
*/
initialFocus?: React.MutableRefObject<any>
}

export { Modal, ModalTitle, ModalOverlay, ModalContent }
export { Modal }
38 changes: 38 additions & 0 deletions src/components/modal/overlay.tsx
@@ -0,0 +1,38 @@
import React, { FC, HTMLAttributes } from 'react'
import { Dialog } from '@headlessui/react'
import styled from '@emotion/styled'

const { Overlay } = Dialog

/**
* Dims out entire background when modal is open
*/
const ModalOverlay: FC<HTMLAttributes<HTMLElement>> = ({
children,
className,
...props
}) => {
const _className = className
? `avocado-modal__overlay ${className}`
: `avocado-modal__overlay`
// just return Overlay from headlessui
return (
<StyledOverlay {...props} className={_className}>
{children}
</StyledOverlay>
)
}

const StyledOverlay = styled<any>(Overlay)`
background: rgba(0, 0, 0, 0.65);
position: fixed;
top: 0;
bottom: 0;
display: flex;
align-items: flex-start;
left: 0;
right: 0;
zindex: -1;
`

export { ModalOverlay }
40 changes: 40 additions & 0 deletions src/components/modal/title.tsx
@@ -0,0 +1,40 @@
import React, { ElementType, FC, HTMLAttributes } from 'react'
import { Dialog } from '@headlessui/react'
import styled from '@emotion/styled'

import colors from '../theme/colors'

// Modal Title
const { Title } = Dialog

const ModalTitle: FC<ModalTitleProps> = ({
children,
className,
as,
...props
}) => {
const _className = className
? `avocado-modal__title ${className}`
: `avocado-modal__title`

return (
<StyledTitle as={as} {...props} className={_className}>
{children}
</StyledTitle>
)
}

interface ModalTitleProps extends HTMLAttributes<HTMLElement> {
/**
* as - specifies the html element the component should be rendered as
*/
as: ElementType<any>
}

const StyledTitle = styled<any>(Title)`
font-weight: 700;
padding-bottom: 0.5em;
border-bottom: 1px solid ${colors.gray[4]};
`

export { ModalTitle }

0 comments on commit 7589537

Please sign in to comment.